[PATCH] D132821: [clang][Parse] Fix crash when emitting template diagnostic

2022-08-29 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added inline comments.



Comment at: clang/include/clang/Basic/DiagnosticParseKinds.td:779
+  "|refers to a variable template||refers to a concept|"
+  "refers to a concept template}1">;
 def err_id_after_template_in_nested_name_spec : Error<

Is "concept template" a term of art? I have never heard of that before.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D132821

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


[PATCH] D132821: [clang][Parse] Fix crash when emitting template diagnostic

2022-08-29 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb accepted this revision.
cjdb added a comment.
This revision is now accepted and ready to land.

Thanks for looking into this so quickly. LGTM with Aaron's suggested changes.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D132821

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


[PATCH] D130867: [clang] adds builtin `std::invoke` and `std::invoke_r`

2022-09-06 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added a comment.

In D130867#3759181 , @aaron.ballman 
wrote:

> Thanks for working on this; these sort of improvements to compile time 
> overhead are very much appreciated!
>
> Has this been tested against libc++ (our preccommit CI doesn't test that), 
> and if so, do all the results come back clean from their test suite? Did you 
> try out any other large scale C++ projects to make sure they don't break?

I've tested it with the libc++ tests (it caught an interesting thing or two), 
range-v3, and whatever else I've built since adding this patch to my local 
install of Clang. I can give a few more large projects a spin if you want 
higher confidence?

In D130867#3768142 , @var-const wrote:

> Out of curiosity, would it be possible to do a benchmark to see how adding 
> `_LIBCPP_NODEBUG` to `std::invoke` would compare to using builtins?

They're within a few hundred bytes of each other when I also apply 
`[[clang::always_inline]]`, but it's still worth applying the built-in. This 
patch helps multiple standard library implementations, so while I encourage 
libc++ to consider decorating `std::invoke`, I do think it's worth the 
implementation existing in Clang too. Another good reason is that by having it 
as a built-in lets me more easily add `__is[_nothrow]_invocable` and 
`__invoke_result`.




Comment at: clang/include/clang/Basic/DiagnosticSemaKinds.td:8411
+  "can't invoke pointer-to-%select{data member|member function}0: expected "
+  "second argument to be a %select{reference|wrapee|pointer}1 to a class "
+  "compatible with %2, got %3">;

aaron.ballman wrote:
> Something's off here, what's a "wrapee"? ("to be a wrapee to a class 
> compatible" doesn't seem grammatically correct.)
"wrapee" refers to the type that's wrapped by `std::reference_wrapper`. I can't 
think of a better name for them, any suggestions?



Comment at: clang/include/clang/Basic/DiagnosticSemaKinds.td:8413-8414
+  "compatible with %2, got %3">;
+def err_invoke_pointer_to_member_drops_qualifiers : Error<
+  "can't invoke pointer-to-member function: '%0' drops '%1' qualifier%s2">;
+def err_invoke_pointer_to_member_ref_qualifiers : Error<

aaron.ballman wrote:
> Can we reuse `err_pointer_to_member_call_drops_quals` instead of making a new 
> diagnostic?
Short answer: yes.

Long answer: I've found that "can't invoke X" to be //really// helpful when 
they've popped up, because it's very obvious that this is to do with 
`std::invoke`, so I'm partial to making 
`err_pointer_to_member_call_drops_quals` toggleable based on that. (I think you 
suggest this two comments down?)



Comment at: clang/lib/Sema/SemaExpr.cpp:267
   auto *Ctor = dyn_cast(FD);
-  if (Ctor && Ctor->isInheritingConstructor())
-Diag(Loc, diag::err_deleted_inherited_ctor_use)
-<< Ctor->getParent()
-<< Ctor->getInheritedConstructor().getConstructor()->getParent();
-  else
-Diag(Loc, diag::err_deleted_function_use);
-  NoteDeletedFunction(FD);
+  if (!IsStdInvoke) {
+if (Ctor && Ctor->isInheritingConstructor())

aaron.ballman wrote:
> Why do we want to suppress the diagnostic here?
I think this is the one where I was getting the same diagnostic twice.



Comment at: clang/lib/Sema/SemaExpr.cpp:14543
   if (Result.isNull()) {
-S.Diag(OpLoc, diag::err_typecheck_indirection_requires_pointer)
-  << OpTy << Op->getSourceRange();
+if (!IsStdInvoke)
+  S.Diag(OpLoc, diag::err_typecheck_indirection_requires_pointer)

aaron.ballman wrote:
> This also surprises me.
Or maybe it was this one. One (or both) of the suppressions is because there 
was a duplicate error.



Comment at: clang/test/SemaCXX/builtin-std-invoke.cpp:295
+int deleted_function() = delete; // expected-note 2 {{'deleted_function' has 
been explicitly marked deleted here}}
+
+struct Incompatible {};

aaron.ballman wrote:
> It would be good to have a test which decays a use of `std::invoke` into a 
> function pointer to make sure that's still possible.
Is that allowed? I thought taking the address of `std::invoke` was ill-formed.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130867

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


[PATCH] D128372: [Clang-Tidy] Empty Check

2022-09-07 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added a comment.

Ping.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D128372

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


[PATCH] D130867: [clang] adds builtin `std::invoke` and `std::invoke_r`

2022-09-09 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb abandoned this revision.
cjdb added a comment.

I had not realised that libc++ was listed as a reviewer. I am going to abandon 
this revision, since I only wish to interact with that community when it is 
both business-critical and unavoidable.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130867

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


[PATCH] D130867: [clang] adds builtin `std::invoke` and `std::invoke_r`

2022-09-11 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added a comment.

In D130867#3781492 , @ldionne wrote:

> In D130867#3781429 , @cjdb wrote:
>
>> I had not realised that libc++ was listed as a reviewer.
>
> The change does have an impact on libc++, so I think it makes sense to look 
> at it not only from the compiler perspective, but from the whole clang/libc++ 
> ecosystem's perspective.
>
>> I am going to abandon this revision, since I only wish to interact with that 
>> community when it is both business-critical and unavoidable.
>
> While you're not saying so explicitly, you seem to be implying some sort of 
> fault on libc++ here, which I don't understand. I am trying to engage in a 
> genuine and productive discussion. I'm asking questions to clarify my 
> understanding of your benchmarks, raising IMO reasonable technical concerns 
> with the patch, and doing so politely unless I missed something. I'm not 
> saying we should not move forward with the patch -- there must be a reason 
> why you put in all this effort into it. I'm merely raising concerns because 
> no, this isn't a black-and-white situation -- there is a tradeoff with this 
> patch.
>
> I don't know whether your comment targets me personally or the libc++ 
> community as a whole, but either way, honestly this sort of "I won't talk to 
> you" behavior is kind of hurtful. If you feel there's something wrong with 
> the libc++ community or with me, the LLVM Foundation has channels to 
> remediate to that, and I encourage you (or anyone feeling bad about any part 
> of LLVM) to use them.

Please revise the emails I sent to you, titled 'libc++ involvement' on 
2022-01-18 and 'RE: RE: libc++ involvement' on 2022-01-20, for the reasons why 
I do not wish to engage with the libc++ community. Friday's commentary simply 
documents why work on this patch has abruptly stopped.

I do not intend to discuss the matter any further in D130867 
.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130867

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


[PATCH] D116280: [clang] adds unary type trait checks as compiler built-ins

2022-06-26 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb updated this revision to Diff 440079.
cjdb added a comment.

rebases


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D116280

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/lib/Sema/SemaType.cpp
  clang/test/SemaCXX/type-traits.cpp

Index: clang/test/SemaCXX/type-traits.cpp
===
--- clang/test/SemaCXX/type-traits.cpp
+++ clang/test/SemaCXX/type-traits.cpp
@@ -345,11 +345,19 @@
 }
 
 typedef Enum EnumType;
+typedef EnumClass EnumClassType;
 
 void is_enum()
 {
   { int arr[T(__is_enum(Enum))]; }
   { int arr[T(__is_enum(EnumType))]; }
+  { int arr[T(__is_enum(SignedEnum))]; }
+  { int arr[T(__is_enum(UnsignedEnum))]; }
+
+  { int arr[T(__is_enum(EnumClass))]; }
+  { int arr[T(__is_enum(EnumClassType))]; }
+  { int arr[T(__is_enum(SignedEnumClass))]; }
+  { int arr[T(__is_enum(UnsignedEnumClass))]; }
 
   { int arr[F(__is_enum(int))]; }
   { int arr[F(__is_enum(Union))]; }
@@ -363,6 +371,29 @@
   { int arr[F(__is_enum(HasAnonymousUnion))]; }
 }
 
+void is_scoped_enum() {
+  { int arr[F(__is_scoped_enum(Enum))]; }
+  { int arr[F(__is_scoped_enum(EnumType))]; }
+  { int arr[F(__is_scoped_enum(SignedEnum))]; }
+  { int arr[F(__is_scoped_enum(UnsignedEnum))]; }
+
+  { int arr[T(__is_scoped_enum(EnumClass))]; }
+  { int arr[T(__is_scoped_enum(EnumClassType))]; }
+  { int arr[T(__is_scoped_enum(SignedEnumClass))]; }
+  { int arr[T(__is_scoped_enum(UnsignedEnumClass))]; }
+
+  { int arr[F(__is_scoped_enum(int))]; }
+  { int arr[F(__is_scoped_enum(Union))]; }
+  { int arr[F(__is_scoped_enum(Int))]; }
+  { int arr[F(__is_scoped_enum(IntAr))]; }
+  { int arr[F(__is_scoped_enum(UnionAr))]; }
+  { int arr[F(__is_scoped_enum(Derives))]; }
+  { int arr[F(__is_scoped_enum(ClassType))]; }
+  { int arr[F(__is_scoped_enum(cvoid))]; }
+  { int arr[F(__is_scoped_enum(IntArNB))]; }
+  { int arr[F(__is_scoped_enum(HasAnonymousUnion))]; }
+}
+
 struct FinalClass final {
 };
 
@@ -702,6 +733,106 @@
   int t31[F(__is_array(cvoid*))];
 }
 
+void is_bounded_array(int n) {
+  int t01[T(__is_bounded_array(IntAr))];
+  int t02[F(__is_bounded_array(IntArNB))];
+  int t03[T(__is_bounded_array(UnionAr))];
+
+  int t10[F(__is_bounded_array(void))];
+  int t11[F(__is_bounded_array(cvoid))];
+  int t12[F(__is_bounded_array(float))];
+  int t13[F(__is_bounded_array(double))];
+  int t14[F(__is_bounded_array(long double))];
+  int t15[F(__is_bounded_array(bool))];
+  int t16[F(__is_bounded_array(char))];
+  int t17[F(__is_bounded_array(signed char))];
+  int t18[F(__is_bounded_array(unsigned char))];
+  int t19[F(__is_bounded_array(wchar_t))];
+  int t20[F(__is_bounded_array(short))];
+  int t21[F(__is_bounded_array(unsigned short))];
+  int t22[F(__is_bounded_array(int))];
+  int t23[F(__is_bounded_array(unsigned int))];
+  int t24[F(__is_bounded_array(long))];
+  int t25[F(__is_bounded_array(unsigned long))];
+  int t26[F(__is_bounded_array(Union))];
+  int t27[F(__is_bounded_array(Derives))];
+  int t28[F(__is_bounded_array(ClassType))];
+  int t29[F(__is_bounded_array(Enum))];
+  int t30[F(__is_bounded_array(void *))];
+  int t31[F(__is_bounded_array(cvoid *))];
+
+  int t32[n];
+  (void)__is_bounded_array(decltype(t32)); // expected-error{{variable length arrays are not supported for '__is_bounded_array'}}
+}
+
+void is_unbounded_array(int n) {
+  int t01[F(__is_unbounded_array(IntAr))];
+  int t02[T(__is_unbounded_array(IntArNB))];
+  int t03[F(__is_unbounded_array(UnionAr))];
+
+  int t10[F(__is_unbounded_array(void))];
+  int t11[F(__is_unbounded_array(cvoid))];
+  int t12[F(__is_unbounded_array(float))];
+  int t13[F(__is_unbounded_array(double))];
+  int t14[F(__is_unbounded_array(long double))];
+  int t15[F(__is_unbounded_array(bool))];
+  int t16[F(__is_unbounded_array(char))];
+  int t17[F(__is_unbounded_array(signed char))];
+  int t18[F(__is_unbounded_array(unsigned char))];
+  int t19[F(__is_unbounded_array(wchar_t))];
+  int t20[F(__is_unbounded_array(short))];
+  int t21[F(__is_unbounded_array(unsigned short))];
+  int t22[F(__is_unbounded_array(int))];
+  int t23[F(__is_unbounded_array(unsigned int))];
+  int t24[F(__is_unbounded_array(long))];
+  int t25[F(__is_unbounded_array(unsigned long))];
+  int t26[F(__is_unbounded_array(Union))];
+  int t27[F(__is_unbounded_array(Derives))];
+  int t28[F(__is_unbounded_array(ClassType))];
+  int t29[F(__is_unbounded_array(Enum))];
+  int t30[F(__is_unbounded_array(void *))];
+  int t31[F(__is_unbounded_array(cvoid *))];
+
+  int t32[n];
+  (void)__is_unbounded_array(decltype(t32)); // expected-error{{variable length arrays are not supported for '__is_unbounded_array'}}
+}
+
+void is_referenceable() {
+  { int a[T(__is_referenceable(int))]; }

[PATCH] D128372: [Clang-Tidy] Empty Check

2022-06-27 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added inline comments.



Comment at: clang-tools-extra/clang-tidy/bugprone/StandaloneEmptyCheck.cpp:76
+
+auto Methods = Arg->getType()->getAsCXXRecordDecl()->methods();
+auto Clear = llvm::find_if(Methods, [](const CXXMethodDecl *F) {

denik wrote:
> Check `getAsCXXRecordDecl()` for null and add a test case.
We should also have a test to ensure `empty(0)` doesn't segfault.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D128372

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


[PATCH] D128372: [Clang-Tidy] Empty Check

2022-07-07 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added inline comments.



Comment at: clang-tools-extra/clang-tidy/bugprone/StandaloneEmptyCheck.cpp:128
+  << FixItHint::CreateReplacement(ReplacementRange, "clear");
+} else {
+  diag(MemberLoc, "ignoring the result of 'empty()'");

Let's eliminate some of these else-clauses by using early exits.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D128372

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


[PATCH] D128372: [Clang-Tidy] Empty Check

2022-07-07 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb accepted this revision.
cjdb added a comment.

Thanks for working on this! I'll merge this on your behalf once there's 
maintainer approval.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D128372

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


[PATCH] D116203: [clang] adds unary type transformations as compiler built-ins

2022-04-01 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added a comment.

In D116203#3255018 , @aaron.ballman 
wrote:

> In D116203#3220165 , @aaron.ballman 
> wrote:
>
>> The summary for the patch explains what's being added, but there's really no 
>> information as to why it's being added. Why do we need these builtins?
>
> Btw, I still think the patch summary should be updated with this information.

Sorry, I completely missed this. Done.

In D116203#3277515 , @zoecarver wrote:

> This patch looks awesome, Chris.
>
> Does it make sense to have builtins for `add_const`, etc.? Isn't `T const` 
> already kind of a builtin for this?

Potentially, but I need a core language lawyer to weigh in here. The library 
wording for `std::add_const::type` is:

> If `T` is a reference, function, or top-level `const`-qualified type, then 
> type names the same type as `T`, otherwise `T const`.

Although my understanding is that the `T const` in this case is redundant (and 
thus not applied per dcl.type.cv ), the 
library wording goes out of its way to say "do nothing".




Comment at: clang/include/clang/AST/Type.h:6488
+  const auto *F = Self.getAs();
+  return F == nullptr ||
+ (F->getMethodQuals().empty() && F->getRefQualifier() == RQ_None);

aaron.ballman wrote:
> cjdb wrote:
> > aaron.ballman wrote:
> > > A function without a prototype is referenceable? (This is more of a 
> > > "should this predicate do anything in C?" kind of question, I suppose.)
> > Does C++ have a notion of non-prototyped functions? I don't think it does? 
> > As such, I'm struggling to model this in a way that makes sense :(
> > 
> > Maybe that's evidence for NAD, maybe it isn't :shrug:
> C++ doesn't have the notion of a function without a prototype (thankfully).
> 
> Should this function assert that it's not called in C mode at all? I don't 
> think asking the question makes sense in C.
I made a change in that this asserts when not in C++ mode.



Comment at: clang/include/clang/Basic/DiagnosticSemaKinds.td:8595
+def err_make_signed_integral_only : Error<
+  "'%select{make_unsigned|make_signed}0' is only compatible with non-bool 
integers and enum types, but was given %1">;
 def ext_typecheck_cond_incompatible_pointers : ExtWarn<

aaron.ballman wrote:
> cjdb wrote:
> > aaron.ballman wrote:
> > > This can be reformatted, I believe, but did you look around to see if an 
> > > existing diagnostic would suffice?
> > Do you have any tips on how to narrow my search? I don't really want to 
> > //read// 11K lines of diagnostics.
> I usually search for "typecheck" for type checking diagnostics. One that 
> looks close is:
> ```
> def err_pragma_loop_invalid_argument_type : Error<
>   "invalid argument of type %0; expected an integer type">;
> ```
> that could likely be changed to something along the lines of:
> ```
> def err_invalid_argument_type : Error<
>   "invalid argument of type %0; expected an integer type %select{|other than 
> 'bool'}1">;
> ```
> (I think enum types are always integer types and so they may not need to be 
> called out in the diagnostic.)
I'm not particularly fond of this one because it doesn't call out the builtin's 
user-facing name. I suppose we could do this, but I'm not sure where to draw 
the line:

```
def err_invalid_argument_type : Error<
  "invalid argument %select{|for 'make_%select{signed|unsigned}2'}1, with type 
%0; expected an integer type %select{|other than 'bool'}3">;
```

This means that users who misuse `std::make_[un]signed` will get a nice 
diagnostic instead of one targeting `__make_[un]signed`, which helps them work 
out where they can fix their code.



Comment at: clang/lib/AST/ASTContext.cpp:5604
 /// savings are minimal and these are rare.
+// Update 2021-12-16: it might be worth revisiting this
 QualType ASTContext::getUnaryTransformType(QualType BaseType,

aaron.ballman wrote:
> cjdb wrote:
> > WDYT @aaron.ballman?
> Are these expected to be less rare now due to your patch? FWIW, I'm fine 
> revisiting if we can measure some value, but I think that's good as a 
> separate patch.
I've got no idea, which is why I'm flagging it. Each of these built-in traits 
makes a call, so it's no longer just `__underlying_type`. Sounds like I can 
resolve for now.



Comment at: clang/lib/AST/ItaniumMangle.cpp:3928
 break;
+  case UnaryTransformType::AddConst:
+Out << "2ac";

aaron.ballman wrote:
> Are these the suggested manglings from the Itanium mangling document, or 
> something you invented yourself?
> 
> Should there be corresponding Microsoft manglings or are those already 
> handled magically?
> 
> Also, test coverage for the manglings?
I copied the mangling from D67052 and then inferred for what's missing over 
there. I'll consult the It

[PATCH] D116203: [clang] adds unary type transformations as compiler built-ins

2022-04-03 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added a comment.

I've noticed that libstdc++ has `using __remove_cv = typename 
remove_cv::type`, which causes Clang to chuck a wobbly. Changing from 
`KEYWORD` to `TYPE_TRAIT_1` didn't seem to fix anything.
Is there a way we can work around this, or should we just rename `__remove_cv` 
and friends to something else?




Comment at: clang/lib/Sema/SemaType.cpp:9227
 
-DiagnoseUseOfDecl(ED, Loc);
+  QualType Underlying = Context.getIntTypeForBitwidth(
+  Context.getIntWidth(BaseType), IsMakeSigned);

rjmccall wrote:
> cjdb wrote:
> > erichkeane wrote:
> > > Can you add a couple of tests to make sure this works with _BitInt?  Note 
> > > that this + the libc++ fixes get this done: 
> > > https://github.com/llvm/llvm-project/issues/50427
> > Done for `_BitInt`. Is there a corresponding unsigned `_BitInt`? Neither 
> > `_BitUint`, `BitUInt`, nor `_UBitInt` work :(
> I believe `_BitInt` works like `int` et al., so it'd be `unsigned _BitInt`, 
All done, thanks!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D116203

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


[PATCH] D130058: [Clang] Diagnose ill-formed constant expression when setting a non fixed enum to a value outside the range of the enumeration values

2022-07-27 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added inline comments.



Comment at: clang/test/SemaCXX/constant-expression-cxx11.cpp:2420
+  constexpr E1 x2 = static_cast(8); // expected-error {{must be 
initialized by a constant expression}}
+  // expected-note@-1 {{integer value 8 is outside the valid range of values 
[-8, 8) for this enumeration type}}
+

erichkeane wrote:
> royjacobson wrote:
> > aaron.ballman wrote:
> > > tahonermann wrote:
> > > > erichkeane wrote:
> > > > > aaron.ballman wrote:
> > > > > > erichkeane wrote:
> > > > > > > aaron.ballman wrote:
> > > > > > > > erichkeane wrote:
> > > > > > > > > Are we ok with how subtle the `[N, M)` syntax is here?
> > > > > > > > FWIW, I pulled this from diagnostics like: 
> > > > > > > > https://github.com/llvm/llvm-project/blob/main/clang/include/clang/Basic/DiagnosticSemaKinds.td#L9904
> > > > > > > >  and 
> > > > > > > > https://github.com/llvm/llvm-project/blob/main/clang/include/clang/Basic/DiagnosticSemaKinds.td#L11541
> > > > > > > Those aren't particularly high quality diagnostics, the first is 
> > > > > > > for builtin ranges (and builtins have notoriously bad 
> > > > > > > diagnostics), the 2nd is for the matrix type, which is only 
> > > > > > > slightly better.
> > > > > > > 
> > > > > > > That said, if you are ok with it, I'm ok, just somewhat afraid 
> > > > > > > it'll be a touch confusing.
> > > > > > Yeah, it's not the best diagnostic, to be sure. The trouble is that 
> > > > > > spelling it out makes it worse IMO: `integer value %0 is outside 
> > > > > > the valid range of values %1 (inclusive) and %2 (exclusive) for 
> > > > > > this enumeration type`
> > > > > Ok then, I can't think of anything better really (PERHAPS something 
> > > > > that says, `integer value %0 is outside of the valid range of values 
> > > > > (%1 - %2 inclusive) for this enumeration type`, so I'm ok living with 
> > > > > it until someone proposes better in a followup patch.
> > > > > 
> > > > > 
> > > > I've never cared for the `[` vs `(` notation to indicate inclusivity vs 
> > > > exclusivity. All I see are unbalanced tokens and I can never remember 
> > > > which brace means what; I have to look it up every time and it isn't an 
> > > > easy search, especially for people that aren't already somewhat 
> > > > familiar with the notation; you have to know to search for something 
> > > > like "range inclusive exclusive notation". I urge use of the more 
> > > > elaborate diagnostic.
> > > I'm fine with being more verbose in the diagnostic so long as it doesn't 
> > > go overboard. I don't really like the wording Erich suggested because it 
> > > can be misinterpreted as both values being inclusive. I can hold my nose 
> > > at what we have above. We're inconsistent in how we report this kind of 
> > > information and it seems like someday we should improve this whole class 
> > > of diagnostics (ones with ranges) to have a consistent display to the 
> > > user. (CC @cjdb for awareness for his project, nothing actionable though.)
> > Maybe `[%1 <= x < %2]`? Feels a bit clumsy, but it disambiguates
> My intent WAS for both values to be inclusive!  That is, we'd say `integer 
> value -8 is outside the valid range of values(0 - 7 inclusive) for this 
> enumeration type`), but the additional logic there is likely a PITA for minor 
> improvement.
> 
> I'm ALSO ok with holding my nose here, but would welcome a patch to improve 
> this diagnostic (and, as Aaron said, ALL range diagnostics!). I, however, am 
> not clever enough to come up with it.
While I like `[%1, %2)` (because I nerd out over maths), I think `%1 <= x < %2` 
will be more accessible to folks who haven't taken university calculus or 
discrete maths.

For @tahonermann specifically: a potential mnemonic is that closed intervals 
use a straight line, which intersects an axis, whereas open intervals are 
curved, which represents them being asymptotic.


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

https://reviews.llvm.org/D130058

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


[PATCH] D116280: [clang] adds unary type trait checks as compiler built-ins

2022-07-30 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb updated this revision to Diff 448806.
cjdb added a subscriber: rsmith.
cjdb added a comment.

I think this covers all the feedback @rsmith has provided, though my treatment 
of `BuildPointerType` and `BuildReferenceType` might be wrong.

Hopefully `__make_signed` and `__make_unsigned` are correct now!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D116280

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/ASTContext.cpp
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/lib/Sema/SemaType.cpp
  clang/test/SemaCXX/type-traits.cpp

Index: clang/test/SemaCXX/type-traits.cpp
===
--- clang/test/SemaCXX/type-traits.cpp
+++ clang/test/SemaCXX/type-traits.cpp
@@ -345,11 +345,19 @@
 }
 
 typedef Enum EnumType;
+typedef EnumClass EnumClassType;
 
 void is_enum()
 {
   { int arr[T(__is_enum(Enum))]; }
   { int arr[T(__is_enum(EnumType))]; }
+  { int arr[T(__is_enum(SignedEnum))]; }
+  { int arr[T(__is_enum(UnsignedEnum))]; }
+
+  { int arr[T(__is_enum(EnumClass))]; }
+  { int arr[T(__is_enum(EnumClassType))]; }
+  { int arr[T(__is_enum(SignedEnumClass))]; }
+  { int arr[T(__is_enum(UnsignedEnumClass))]; }
 
   { int arr[F(__is_enum(int))]; }
   { int arr[F(__is_enum(Union))]; }
@@ -363,6 +371,29 @@
   { int arr[F(__is_enum(HasAnonymousUnion))]; }
 }
 
+void is_scoped_enum() {
+  { int arr[F(__is_scoped_enum(Enum))]; }
+  { int arr[F(__is_scoped_enum(EnumType))]; }
+  { int arr[F(__is_scoped_enum(SignedEnum))]; }
+  { int arr[F(__is_scoped_enum(UnsignedEnum))]; }
+
+  { int arr[T(__is_scoped_enum(EnumClass))]; }
+  { int arr[T(__is_scoped_enum(EnumClassType))]; }
+  { int arr[T(__is_scoped_enum(SignedEnumClass))]; }
+  { int arr[T(__is_scoped_enum(UnsignedEnumClass))]; }
+
+  { int arr[F(__is_scoped_enum(int))]; }
+  { int arr[F(__is_scoped_enum(Union))]; }
+  { int arr[F(__is_scoped_enum(Int))]; }
+  { int arr[F(__is_scoped_enum(IntAr))]; }
+  { int arr[F(__is_scoped_enum(UnionAr))]; }
+  { int arr[F(__is_scoped_enum(Derives))]; }
+  { int arr[F(__is_scoped_enum(ClassType))]; }
+  { int arr[F(__is_scoped_enum(cvoid))]; }
+  { int arr[F(__is_scoped_enum(IntArNB))]; }
+  { int arr[F(__is_scoped_enum(HasAnonymousUnion))]; }
+}
+
 struct FinalClass final {
 };
 
@@ -702,6 +733,106 @@
   int t31[F(__is_array(cvoid*))];
 }
 
+void is_bounded_array(int n) {
+  int t01[T(__is_bounded_array(IntAr))];
+  int t02[F(__is_bounded_array(IntArNB))];
+  int t03[T(__is_bounded_array(UnionAr))];
+
+  int t10[F(__is_bounded_array(void))];
+  int t11[F(__is_bounded_array(cvoid))];
+  int t12[F(__is_bounded_array(float))];
+  int t13[F(__is_bounded_array(double))];
+  int t14[F(__is_bounded_array(long double))];
+  int t15[F(__is_bounded_array(bool))];
+  int t16[F(__is_bounded_array(char))];
+  int t17[F(__is_bounded_array(signed char))];
+  int t18[F(__is_bounded_array(unsigned char))];
+  int t19[F(__is_bounded_array(wchar_t))];
+  int t20[F(__is_bounded_array(short))];
+  int t21[F(__is_bounded_array(unsigned short))];
+  int t22[F(__is_bounded_array(int))];
+  int t23[F(__is_bounded_array(unsigned int))];
+  int t24[F(__is_bounded_array(long))];
+  int t25[F(__is_bounded_array(unsigned long))];
+  int t26[F(__is_bounded_array(Union))];
+  int t27[F(__is_bounded_array(Derives))];
+  int t28[F(__is_bounded_array(ClassType))];
+  int t29[F(__is_bounded_array(Enum))];
+  int t30[F(__is_bounded_array(void *))];
+  int t31[F(__is_bounded_array(cvoid *))];
+
+  int t32[n];
+  (void)__is_bounded_array(decltype(t32)); // expected-error{{variable length arrays are not supported for '__is_bounded_array'}}
+}
+
+void is_unbounded_array(int n) {
+  int t01[F(__is_unbounded_array(IntAr))];
+  int t02[T(__is_unbounded_array(IntArNB))];
+  int t03[F(__is_unbounded_array(UnionAr))];
+
+  int t10[F(__is_unbounded_array(void))];
+  int t11[F(__is_unbounded_array(cvoid))];
+  int t12[F(__is_unbounded_array(float))];
+  int t13[F(__is_unbounded_array(double))];
+  int t14[F(__is_unbounded_array(long double))];
+  int t15[F(__is_unbounded_array(bool))];
+  int t16[F(__is_unbounded_array(char))];
+  int t17[F(__is_unbounded_array(signed char))];
+  int t18[F(__is_unbounded_array(unsigned char))];
+  int t19[F(__is_unbounded_array(wchar_t))];
+  int t20[F(__is_unbounded_array(short))];
+  int t21[F(__is_unbounded_array(unsigned short))];
+  int t22[F(__is_unbounded_array(int))];
+  int t23[F(__is_unbounded_array(unsigned int))];
+  int t24[F(__is_unbounded_array(long))];
+  int t25[F(__is_unbounded_array(unsigned long))];
+  int t26[F(__is_unbounded_array(Union))];
+  int t27[F(__is_unbounded_array(Derives))];
+  int t28[F(__is_unbounded_array(ClassType))];
+  int t29[F(__is_unbounded_array(Enum))];
+  int t30[F(__is_unbounded_array(void *))];
+  int

[PATCH] D116203: [clang] adds unary type transformations as compiler built-ins

2022-07-30 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb marked 13 inline comments as done.
cjdb added inline comments.



Comment at: clang/lib/Parse/ParseExpr.cpp:1755-1756
+  Tok.setKind(tok::identifier);
+  Diag(Tok, diag::ext_keyword_as_ident)
+  << Tok.getIdentifierInfo()->getName() << 0;
+  goto ParseIdentifier;

rsmith wrote:
> Is it feasible to also produce this warning for the corresponding case in 
> `MaybeParseTypeTransformTypeSpecifier` / the callers of that function?
Will this risk sending out the warning twice, and if so, can the diagnostic 
engine handle that?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D116203

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


[PATCH] D130867: WORK-IN-PROGRESS [clang] adds builtin `std::invoke` and `std::invoke_r`

2022-07-31 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb created this revision.
cjdb added reviewers: aaron.ballman, rsmith.
Herald added a reviewer: NoQ.
Herald added a project: All.
cjdb requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

`std::invoke` and `std::invoke_r` are fairly easy to implement as
library functions using overloads, but this is an expensive
implementation. They can also be implemented using `if constexpr`, but
this requires duplicating the logic for the _noexcept-specifier_, which
makes the implementation brittle.

This commit lifts these functions into the compiler to avoid these
problems. It also adds the associated type-traits:

- `__invoke_result`
- `__is_invocable`
- `__is_invocable_r`
- `__is_nothrow_invocable`
- `__is_nothrow_invocable_r`

---

THIS IS A WORK IS PROGRESS

The following things need to be done:

- add all of the type traits
- fix up diagnostics
- benchmark against the aforementioned library implementaitons

I'm putting this up for an early review as I'd like to see if this is
headed down the right path, if there's anything I'm missing from the
function's side of things, and because I'd appreciate input on the
diagnostics (while I'm happy with the diags themselves, I'm less than
happy about how I'm handling them, and am wondering if the process
should be more invasive).

On diagnostics: it might be undesirable for the error to say the
expression, because expressions might be long. In this case, it would be
replaced with the entity kind (e.g. "can't invoke function", etc.), but
I feel this loses a lot of the diagnostic's expressability, and I'm
unhappy about that.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D130867

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/Builtins.def
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/ExprConstant.cpp
  clang/lib/Analysis/BodyFarm.cpp
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/test/SemaCXX/builtin-std-invoke.cpp

Index: clang/test/SemaCXX/builtin-std-invoke.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/builtin-std-invoke.cpp
@@ -0,0 +1,439 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+
+namespace std {
+template 
+void invoke(F &&, Args &&...); // expected-note{{requires at least 1 argument, but 0 were provided}}
+
+template 
+R invoke_r(F &&, Args &&...); // expected-note{{requires at least 1 argument, but 0 were provided}}
+
+// Slightly different to the real deal to simplify test.
+template 
+class reference_wrapper {
+public:
+  constexpr reference_wrapper(T &t) : data(&t) {}
+
+  constexpr operator T &() const noexcept { return *data; }
+
+private:
+  T *data;
+};
+} // namespace std
+
+#define assert(...)   \
+  if (!(__VA_ARGS__)) \
+__builtin_unreachable();
+
+struct ThrowingInt {
+  constexpr ThrowingInt(int x) : value(x) {}
+
+  int value;
+};
+
+template 
+constexpr void bullet_1(F f, T &&t, Args... args) {
+  assert(std::invoke(f, static_cast(t), args...) == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke(f, static_cast(t), args...)), Returns));
+  static_assert(noexcept(std::invoke(f, static_cast(t), args...)) == IsNoexcept);
+
+  assert(std::invoke_r(f, static_cast(t), args...) == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke_r(f, static_cast(t), args...)), double));
+  static_assert(noexcept(std::invoke_r(f, static_cast(t), args...)) == IsNoexcept);
+
+  assert(std::invoke_r(f, static_cast(t), args...).value == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke_r(f, static_cast(t), args...)), ThrowingInt));
+  static_assert(!noexcept(std::invoke_r(f, static_cast(t), args...)));
+}
+
+template 
+constexpr void bullet_2(F f, T &t, Args... args) {
+  std::reference_wrapper rw(t);
+  assert(std::invoke(f, rw, args...) == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke(f, rw, args...)), Returns));
+  static_assert(noexcept(std::invoke(f, rw, args...)) == IsNoexcept);
+
+  assert(std::invoke_r(f, rw, args...) == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke_r(f, rw, args...)), double));
+  static_assert(noexcept(std::invoke_r(f, rw, args...)) == IsNoexcept);
+
+  assert(std::invoke_r(f, rw, args...).value == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke_r(f, rw, args...)), ThrowingInt));
+  static_assert(!noexcept(std::invoke_r(f, rw, args...)));
+}
+
+template 
+class PointerWrapper {
+public:
+  constexpr explicit PointerWrapper(T &t) noexcept : p(&t) {}
+
+  constexpr T &operator*() const noexcept { return *p; }
+
+private:
+  T *p;
+};
+
+template 
+constexpr void bullet_3(F f, T &t, Args... args) {
+  assert(std::invoke(f, &t, args...) == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke(f, &t

[PATCH] D131084: Add support for specifying the severity of a SARIF Result.

2022-08-03 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added a comment.

In D131084#3697211 , @vaibhav.y wrote:

> Submitting for review:
>
> Some notes:
>
> There are a couple of ways I think we can acheive this, per the spec:
>
> 1. The reportingDescriptor (rule) objects can be given a default 
> configuration property 
> ,
>  which can set the default warning level and other data such as rule 
> parameters etc.
> 2. The reportingDescriptor objects can omit the default configuration (which 
> then allows operating with warning as default), and the level is then set 
> when the result is reported.
>
> The first approach would be "more correct", what are your thoughts on this? 
> Would we benefit from having per-diagnostic configuration?
>
> There is also the question about the "kind" of results in clang. From my 
> reading of the spec 
> ,
>  it seems that "fail" is the only case that applies to us because:
>
> - "pass": Implies no issue was found.
> - "open": This value is used by proof-based tools. It could also mean 
> additional assertions required
> - "informational": The specified rule was evaluated and produced a purely 
> informational result that does not indicate the presence of a problem
> - "notApplicable": The rule specified by ruleId was not evaluated, because it 
> does not apply to the analysis target.
>
> Of these "open" and "notApplicable" seem to be ones that *could* come to use 
> but I'm not sure where / what kind of diagnostics would use these. Probably 
> clang-tidy's `bugprone-*` suite?
>
> Let me know what you think is a good way to approach this wrt clang's 
> diagnostics system.

Hmm, we can probably use "informational" for notes, warnings, and remarks, but 
I'm kinda partial to proposing the latter two upstream.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131084

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


[PATCH] D131084: Add support for specifying the severity of a SARIF Result.

2022-08-03 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added a comment.

It seems I got confused and conflated the two this morning.

In D131084#3697525 , @vaibhav.y wrote:

>> Hmm, we can probably use "informational" for notes, warnings, and remarks, 
>> but I'm kinda partial to proposing the latter two upstream.
>
> Interesting,  I agree that remarks could fit under "informational".
>
> As for notes: As I understand it they are always child diagnostics of 
> warnings/errors, so seems it would be okay to associate these with the "fail" 
> kind.

I don't think classifying warnings as "fail" is right unless `-Werror` is being 
used. For notes, I think there may be two options, if we don't want to use 
informational:

- inherit from the parent diagnostic
- use notApplicable, since they don't have any influence on their own



In D131084#3697308 , @denik wrote:

> In D131084#3697256 , @cjdb wrote:
>
>> In D131084#3697211 , @vaibhav.y 
>> wrote:
>>
>>> Submitting for review:
>>>
>>> Some notes:
>>>
>>> There are a couple of ways I think we can acheive this, per the spec:
>>>
>>> 1. The reportingDescriptor (rule) objects can be given a default 
>>> configuration property 
>>> ,
>>>  which can set the default warning level and other data such as rule 
>>> parameters etc.
>>> 2. The reportingDescriptor objects can omit the default configuration 
>>> (which then allows operating with warning as default), and the level is 
>>> then set when the result is reported.
>>>
>>> The first approach would be "more correct", what are your thoughts on this? 
>>> Would we benefit from having per-diagnostic configuration?
>>>
>>> There is also the question about the "kind" of results in clang. From my 
>>> reading of the spec 
>>> ,
>>>  it seems that "fail" is the only case that applies to us because:
>>>
>>> - "pass": Implies no issue was found.
>>> - "open": This value is used by proof-based tools. It could also mean 
>>> additional assertions required
>>> - "informational": The specified rule was evaluated and produced a purely 
>>> informational result that does not indicate the presence of a problem
>>> - "notApplicable": The rule specified by ruleId was not evaluated, because 
>>> it does not apply to the analysis target.
>>>
>>> Of these "open" and "notApplicable" seem to be ones that *could* come to 
>>> use but I'm not sure where / what kind of diagnostics would use these. 
>>> Probably clang-tidy's `bugprone-*` suite?
>>>
>>> Let me know what you think is a good way to approach this wrt clang's 
>>> diagnostics system.
>>
>> Hmm, we can probably use "informational" for notes, warnings, and remarks, 
>> but I'm kinda partial to proposing the latter two upstream.
>
> I think we can skip `kind` in the clang diagnostic. I found this:
>
>> If kind is absent, it SHALL default to "fail".
>> If level has any value other than "none" and kind is present, then kind 
>> SHALL have the value "fail".

If skipping the kind defaults to fail, then we shouldn't skip it, because 
getting a warning or remark doesn't necessarily mean that the build has failed.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131084

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


[PATCH] D131084: Add support for specifying the severity of a SARIF Result.

2022-08-04 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added a subscriber: Naghasan.
cjdb added a comment.

In D131084#3699223 , @aaron.ballman 
wrote:

> In D131084#3697678 , @cjdb wrote:
>
>> It seems I got confused and conflated the two this morning.
>>
>> In D131084#3697525 , @vaibhav.y 
>> wrote:
>>
 Hmm, we can probably use "informational" for notes, warnings, and remarks, 
 but I'm kinda partial to proposing the latter two upstream.
>>>
>>> Interesting,  I agree that remarks could fit under "informational".
>>>
>>> As for notes: As I understand it they are always child diagnostics of 
>>> warnings/errors, so seems it would be okay to associate these with the 
>>> "fail" kind.
>>
>> I don't think classifying warnings as "fail" is right unless `-Werror` is 
>> being used. For notes, I think there may be two options, if we don't want to 
>> use informational:
>>
>> - inherit from the parent diagnostic
>> - use notApplicable, since they don't have any influence on their own
>>
>>
>>
>> In D131084#3697308 , @denik wrote:
>>
>>> In D131084#3697256 , @cjdb wrote:
>>>
 In D131084#3697211 , @vaibhav.y 
 wrote:

> Submitting for review:
>
> Some notes:
>
> There are a couple of ways I think we can acheive this, per the spec:
>
> 1. The reportingDescriptor (rule) objects can be given a default 
> configuration property 
> ,
>  which can set the default warning level and other data such as rule 
> parameters etc.
> 2. The reportingDescriptor objects can omit the default configuration 
> (which then allows operating with warning as default), and the level is 
> then set when the result is reported.
>
> The first approach would be "more correct", what are your thoughts on 
> this? Would we benefit from having per-diagnostic configuration?
>
> There is also the question about the "kind" of results in clang. From my 
> reading of the spec 
> ,
>  it seems that "fail" is the only case that applies to us because:
>
> - "pass": Implies no issue was found.
> - "open": This value is used by proof-based tools. It could also mean 
> additional assertions required
> - "informational": The specified rule was evaluated and produced a purely 
> informational result that does not indicate the presence of a problem
> - "notApplicable": The rule specified by ruleId was not evaluated, 
> because it does not apply to the analysis target.
>
> Of these "open" and "notApplicable" seem to be ones that *could* come to 
> use but I'm not sure where / what kind of diagnostics would use these. 
> Probably clang-tidy's `bugprone-*` suite?
>
> Let me know what you think is a good way to approach this wrt clang's 
> diagnostics system.

 Hmm, we can probably use "informational" for notes, warnings, and remarks, 
 but I'm kinda partial to proposing the latter two upstream.
>>>
>>> I think we can skip `kind` in the clang diagnostic. I found this:
>>>
 If kind is absent, it SHALL default to "fail".
 If level has any value other than "none" and kind is present, then kind 
 SHALL have the value "fail".
>>
>> If skipping the kind defaults to fail, then we shouldn't skip it, because 
>> getting a warning or remark doesn't necessarily mean that the build has 
>> failed.
>
> My suggestion is that we only need to worry about two kinds: `fail` for 
> warnings and errors and `informational` for remarks. When the kind if `fail`, 
> I'd expect we'd use the level `warning` or `error`.
>
> Notes are interesting though. Sometimes they're extra information about the 
> diagnostic on the given line, so I was kind of expecting they'd be specified 
> via `attachments` in that case. But they can also sometimes be used to 
> represent code flow (like in some CFG based warnings where we're showing 
> where something was called from), and they can also sometimes be a related 
> location (like "declared here" notes). Perhaps we may want to expose those to 
> SARIF in different ways depending on the situation?

I proposed relaxing the kind upstream last night. 
, since I think that it 
might be good to discern when a warning isn't an error with 
`warning`/`informational`, because then consumers could trivially treat them 
differently. I think `review` is the best one for remarks, because some of them 
do communicate potential problems 
(`remark_fe_backend_optimization_remark_analysis_aliasing` is the only public 
one I can see that's like this, but I do recall a f

[PATCH] D130894: [clang] Print more information about failed static assertions

2022-08-05 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added a comment.

Thank you so much for working on this! It's been on my todo list for a while 
and just haven't gotten around to it.

In D130894#3702166 , @aaron.ballman 
wrote:

> In D130894#3701749 , @tbaeder wrote:
>
>> For the record, the output now looks something like this:
>>
>>   test.cpp:24:1: error: static assertion failed due to requirement 'c != c'
>>   static_assert(c != c);
>>   ^ ~~
>>   test.cpp:24:17: note: expression evaluates to '('0' != '0')'
>>   static_assert(c != c);
>> ~~^~~~
>
> This looks hard to read to me...
>
>> test.cpp:25:1: error: static assertion failed due to requirement 'c > 'a''
>> static_assert(c > 'a');
>> ^ ~~~
>> test.cpp:25:17: note: expression evaluates to '('0' > 'a')'
>
> Same confusion here -- it took me a while to realize what's happening is that 
> we're quoting the part outside of the parens and that's throwing me for a 
> loop. We typically quote things that are syntax but in this case, the parens 
> are not part of the syntax and so the surrounding quotes are catching me. 
> Given that parens are being used as a visual delimiter and a single quote 
> serves the same purpose, I would expect something more like:
>
>   test.cpp:25:17: note: expression evaluates to ''0' > 'a''
>   test.cpp:26:17: note: expression evaluates to '0 > 'a''
>   test.cpp:27:17: note: expression evaluates to '14 > 5'
>   test.cpp:28:17: note: expression evaluates to 'true == false'
>   test.cpp:29:17: note: expression evaluates to 'nullptr != nullptr'
>
> Adding a few more folks as reviewers to see if there is a consensus position 
> on how to proceed.

Agreed on confusion, but `''0' > 'a''` is painful to read. Sadly, short of 
changing quotes to backticks (something that'd be good for non-terminal-based 
consumers of SARIF), I'm not sure I can suggest anything better in one line. If 
we can span multiple lines, which I think would improve readability:

  test.cpp:25:17: note: expression evaluates with:
LHS: '0'
RHS: 'a'
  test.cpp:26:17: note: expression evaluates with:
LHS: 0
RHS: 'a'
  test.cpp:27:17: note: expression evaluates with:
LHS: 14
RHS: 5
  test.cpp:28:17: note: expression evaluates with:
LHS: true
RHS: false
  test.cpp:29:17: note: expression evaluates with:
LHS: nullptr
RHS: nullptr

My assertion library follows what Catch2 and simple-test do, and uses `Actual` 
and `Expected`, but I'm not sure hardcoding those terms into Clang is a good 
idea.


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

https://reviews.llvm.org/D130894

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


[PATCH] D130867: [clang] adds builtin `std::invoke` and `std::invoke_r`

2022-08-06 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb updated this revision to Diff 450581.
cjdb retitled this revision from "WORK-IN-PROGRESS [clang] adds builtin 
`std::invoke` and `std::invoke_r`" to "[clang] adds builtin `std::invoke` and 
`std::invoke_r`".
cjdb edited the summary of this revision.
cjdb added a comment.

updates commit message

- changes message so that it's accurate
- no longer adding type traits in this commit
- adds bechmark

updates diagnoses so that they're more accurate


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130867

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/Builtins.def
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/ExprConstant.cpp
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/test/SemaCXX/builtin-std-invoke.cpp

Index: clang/test/SemaCXX/builtin-std-invoke.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/builtin-std-invoke.cpp
@@ -0,0 +1,468 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+
+namespace std {
+template 
+void invoke(F &&, Args &&...); // expected-note{{requires at least 1 argument, but 0 were provided}}
+
+template 
+R invoke_r(F &&, Args &&...); // expected-note{{requires at least 1 argument, but 0 were provided}}
+
+// Slightly different to the real deal to simplify test.
+template 
+class reference_wrapper {
+public:
+  constexpr reference_wrapper(T &t) : data(&t) {}
+
+  constexpr operator T &() const noexcept { return *data; }
+
+private:
+  T *data;
+};
+} // namespace std
+
+#define assert(...)   \
+  if (!(__VA_ARGS__)) \
+__builtin_unreachable();
+
+struct ThrowingInt {
+  constexpr ThrowingInt(int x) : value(x) {}
+
+  int value;
+};
+
+template 
+constexpr void bullet_1(F f, T &&t, Args... args) {
+  assert(std::invoke(f, static_cast(t), args...) == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke(f, static_cast(t), args...)), Returns));
+  static_assert(noexcept(std::invoke(f, static_cast(t), args...)) == IsNoexcept);
+
+  assert(std::invoke_r(f, static_cast(t), args...) == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke_r(f, static_cast(t), args...)), double));
+  static_assert(noexcept(std::invoke_r(f, static_cast(t), args...)) == IsNoexcept);
+
+  assert(std::invoke_r(f, static_cast(t), args...).value == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke_r(f, static_cast(t), args...)), ThrowingInt));
+  static_assert(!noexcept(std::invoke_r(f, static_cast(t), args...)));
+}
+
+template 
+constexpr void bullet_2(F f, T &t, Args... args) {
+  std::reference_wrapper rw(t);
+  assert(std::invoke(f, rw, args...) == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke(f, rw, args...)), Returns));
+  static_assert(noexcept(std::invoke(f, rw, args...)) == IsNoexcept);
+
+  assert(std::invoke_r(f, rw, args...) == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke_r(f, rw, args...)), double));
+  static_assert(noexcept(std::invoke_r(f, rw, args...)) == IsNoexcept);
+
+  assert(std::invoke_r(f, rw, args...).value == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke_r(f, rw, args...)), ThrowingInt));
+  static_assert(!noexcept(std::invoke_r(f, rw, args...)));
+}
+
+template 
+class PointerWrapper {
+public:
+  constexpr explicit PointerWrapper(T &t) noexcept : p(&t) {}
+
+  constexpr T &operator*() const noexcept { return *p; }
+
+private:
+  T *p;
+};
+
+template 
+constexpr void bullet_3(F f, T &t, Args... args) {
+  assert(std::invoke(f, &t, args...) == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke(f, &t, args...)), Returns));
+  static_assert(noexcept(std::invoke(f, &t, args...)) == IsNoexcept);
+
+  assert(std::invoke(f, PointerWrapper(t), args...) == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke(f, PointerWrapper(t), args...)), Returns));
+  static_assert(noexcept(std::invoke(f, PointerWrapper(t), args...)) == IsNoexcept);
+
+  assert(std::invoke_r(f, &t, args...) == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke_r(f, &t, args...)), double));
+  static_assert(noexcept(std::invoke_r(f, &t, args...)) == IsNoexcept);
+
+  assert(std::invoke_r(f, PointerWrapper(t), args...) == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke_r(f, PointerWrapper(t), args...)), double));
+  static_assert(noexcept(std::invoke_r(f, PointerWrapper(t), args...)) == IsNoexcept);
+
+  assert(std::invoke_r(f, &t, args...).value == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke_r(f, &t, args...)), ThrowingInt));
+  static_assert(!noexcept(std::invoke_r(f, &t, args...)));
+
+  assert(std::invoke_r(f, PointerWrapper(t), args...).value == ExpectedResult);
+  static

[PATCH] D130867: [clang] adds builtin `std::invoke` and `std::invoke_r`

2022-08-06 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb updated this revision to Diff 450584.
cjdb added a comment.

adds logic to diagnose misqualified pointer-to-member functions


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130867

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/Builtins.def
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/ExprConstant.cpp
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/test/SemaCXX/builtin-std-invoke.cpp

Index: clang/test/SemaCXX/builtin-std-invoke.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/builtin-std-invoke.cpp
@@ -0,0 +1,496 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+
+namespace std {
+template 
+void invoke(F &&, Args &&...); // expected-note{{requires at least 1 argument, but 0 were provided}}
+
+template 
+R invoke_r(F &&, Args &&...); // expected-note{{requires at least 1 argument, but 0 were provided}}
+
+// Slightly different to the real deal to simplify test.
+template 
+class reference_wrapper {
+public:
+  constexpr reference_wrapper(T &t) : data(&t) {}
+
+  constexpr operator T &() const noexcept { return *data; }
+
+private:
+  T *data;
+};
+} // namespace std
+
+#define assert(...)   \
+  if (!(__VA_ARGS__)) \
+__builtin_unreachable();
+
+struct ThrowingInt {
+  constexpr ThrowingInt(int x) : value(x) {}
+
+  int value;
+};
+
+template 
+constexpr void bullet_1(F f, T &&t, Args... args) {
+  assert(std::invoke(f, static_cast(t), args...) == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke(f, static_cast(t), args...)), Returns));
+  static_assert(noexcept(std::invoke(f, static_cast(t), args...)) == IsNoexcept);
+
+  assert(std::invoke_r(f, static_cast(t), args...) == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke_r(f, static_cast(t), args...)), double));
+  static_assert(noexcept(std::invoke_r(f, static_cast(t), args...)) == IsNoexcept);
+
+  assert(std::invoke_r(f, static_cast(t), args...).value == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke_r(f, static_cast(t), args...)), ThrowingInt));
+  static_assert(!noexcept(std::invoke_r(f, static_cast(t), args...)));
+}
+
+template 
+constexpr void bullet_2(F f, T &t, Args... args) {
+  std::reference_wrapper rw(t);
+  assert(std::invoke(f, rw, args...) == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke(f, rw, args...)), Returns));
+  static_assert(noexcept(std::invoke(f, rw, args...)) == IsNoexcept);
+
+  assert(std::invoke_r(f, rw, args...) == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke_r(f, rw, args...)), double));
+  static_assert(noexcept(std::invoke_r(f, rw, args...)) == IsNoexcept);
+
+  assert(std::invoke_r(f, rw, args...).value == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke_r(f, rw, args...)), ThrowingInt));
+  static_assert(!noexcept(std::invoke_r(f, rw, args...)));
+}
+
+template 
+class PointerWrapper {
+public:
+  constexpr explicit PointerWrapper(T &t) noexcept : p(&t) {}
+
+  constexpr T &operator*() const noexcept { return *p; }
+
+private:
+  T *p;
+};
+
+template 
+constexpr void bullet_3(F f, T &t, Args... args) {
+  assert(std::invoke(f, &t, args...) == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke(f, &t, args...)), Returns));
+  static_assert(noexcept(std::invoke(f, &t, args...)) == IsNoexcept);
+
+  assert(std::invoke(f, PointerWrapper(t), args...) == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke(f, PointerWrapper(t), args...)), Returns));
+  static_assert(noexcept(std::invoke(f, PointerWrapper(t), args...)) == IsNoexcept);
+
+  assert(std::invoke_r(f, &t, args...) == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke_r(f, &t, args...)), double));
+  static_assert(noexcept(std::invoke_r(f, &t, args...)) == IsNoexcept);
+
+  assert(std::invoke_r(f, PointerWrapper(t), args...) == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke_r(f, PointerWrapper(t), args...)), double));
+  static_assert(noexcept(std::invoke_r(f, PointerWrapper(t), args...)) == IsNoexcept);
+
+  assert(std::invoke_r(f, &t, args...).value == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke_r(f, &t, args...)), ThrowingInt));
+  static_assert(!noexcept(std::invoke_r(f, &t, args...)));
+
+  assert(std::invoke_r(f, PointerWrapper(t), args...).value == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke_r(f, PointerWrapper(t), args...)), ThrowingInt));
+  static_assert(!noexcept(std::invoke_r(f, PointerWrapper(t), args...)));
+}
+
+template 
+constexpr bool bullets_1_through_3(T t) {
+  bullet_1(&T::plus, t, 3, -3);
+  bullet_1(&T::minus, static_cast(t), 1, 2, 3);
+  bullet_1(&T::sq

[PATCH] D116280: [clang] adds unary type trait checks as compiler built-ins

2022-08-06 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb updated this revision to Diff 450585.
cjdb added a comment.

fixes commit update mistake and rebases to ToT


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D116280

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/TokenKinds.def
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/lib/Sema/SemaType.cpp
  clang/test/SemaCXX/type-traits.cpp

Index: clang/test/SemaCXX/type-traits.cpp
===
--- clang/test/SemaCXX/type-traits.cpp
+++ clang/test/SemaCXX/type-traits.cpp
@@ -345,11 +345,19 @@
 }
 
 typedef Enum EnumType;
+typedef EnumClass EnumClassType;
 
 void is_enum()
 {
   { int arr[T(__is_enum(Enum))]; }
   { int arr[T(__is_enum(EnumType))]; }
+  { int arr[T(__is_enum(SignedEnum))]; }
+  { int arr[T(__is_enum(UnsignedEnum))]; }
+
+  { int arr[T(__is_enum(EnumClass))]; }
+  { int arr[T(__is_enum(EnumClassType))]; }
+  { int arr[T(__is_enum(SignedEnumClass))]; }
+  { int arr[T(__is_enum(UnsignedEnumClass))]; }
 
   { int arr[F(__is_enum(int))]; }
   { int arr[F(__is_enum(Union))]; }
@@ -363,6 +371,29 @@
   { int arr[F(__is_enum(HasAnonymousUnion))]; }
 }
 
+void is_scoped_enum() {
+  { int arr[F(__is_scoped_enum(Enum))]; }
+  { int arr[F(__is_scoped_enum(EnumType))]; }
+  { int arr[F(__is_scoped_enum(SignedEnum))]; }
+  { int arr[F(__is_scoped_enum(UnsignedEnum))]; }
+
+  { int arr[T(__is_scoped_enum(EnumClass))]; }
+  { int arr[T(__is_scoped_enum(EnumClassType))]; }
+  { int arr[T(__is_scoped_enum(SignedEnumClass))]; }
+  { int arr[T(__is_scoped_enum(UnsignedEnumClass))]; }
+
+  { int arr[F(__is_scoped_enum(int))]; }
+  { int arr[F(__is_scoped_enum(Union))]; }
+  { int arr[F(__is_scoped_enum(Int))]; }
+  { int arr[F(__is_scoped_enum(IntAr))]; }
+  { int arr[F(__is_scoped_enum(UnionAr))]; }
+  { int arr[F(__is_scoped_enum(Derives))]; }
+  { int arr[F(__is_scoped_enum(ClassType))]; }
+  { int arr[F(__is_scoped_enum(cvoid))]; }
+  { int arr[F(__is_scoped_enum(IntArNB))]; }
+  { int arr[F(__is_scoped_enum(HasAnonymousUnion))]; }
+}
+
 struct FinalClass final {
 };
 
@@ -702,6 +733,106 @@
   int t31[F(__is_array(cvoid*))];
 }
 
+void is_bounded_array(int n) {
+  int t01[T(__is_bounded_array(IntAr))];
+  int t02[F(__is_bounded_array(IntArNB))];
+  int t03[T(__is_bounded_array(UnionAr))];
+
+  int t10[F(__is_bounded_array(void))];
+  int t11[F(__is_bounded_array(cvoid))];
+  int t12[F(__is_bounded_array(float))];
+  int t13[F(__is_bounded_array(double))];
+  int t14[F(__is_bounded_array(long double))];
+  int t15[F(__is_bounded_array(bool))];
+  int t16[F(__is_bounded_array(char))];
+  int t17[F(__is_bounded_array(signed char))];
+  int t18[F(__is_bounded_array(unsigned char))];
+  int t19[F(__is_bounded_array(wchar_t))];
+  int t20[F(__is_bounded_array(short))];
+  int t21[F(__is_bounded_array(unsigned short))];
+  int t22[F(__is_bounded_array(int))];
+  int t23[F(__is_bounded_array(unsigned int))];
+  int t24[F(__is_bounded_array(long))];
+  int t25[F(__is_bounded_array(unsigned long))];
+  int t26[F(__is_bounded_array(Union))];
+  int t27[F(__is_bounded_array(Derives))];
+  int t28[F(__is_bounded_array(ClassType))];
+  int t29[F(__is_bounded_array(Enum))];
+  int t30[F(__is_bounded_array(void *))];
+  int t31[F(__is_bounded_array(cvoid *))];
+
+  int t32[n];
+  (void)__is_bounded_array(decltype(t32)); // expected-error{{variable length arrays are not supported for '__is_bounded_array'}}
+}
+
+void is_unbounded_array(int n) {
+  int t01[F(__is_unbounded_array(IntAr))];
+  int t02[T(__is_unbounded_array(IntArNB))];
+  int t03[F(__is_unbounded_array(UnionAr))];
+
+  int t10[F(__is_unbounded_array(void))];
+  int t11[F(__is_unbounded_array(cvoid))];
+  int t12[F(__is_unbounded_array(float))];
+  int t13[F(__is_unbounded_array(double))];
+  int t14[F(__is_unbounded_array(long double))];
+  int t15[F(__is_unbounded_array(bool))];
+  int t16[F(__is_unbounded_array(char))];
+  int t17[F(__is_unbounded_array(signed char))];
+  int t18[F(__is_unbounded_array(unsigned char))];
+  int t19[F(__is_unbounded_array(wchar_t))];
+  int t20[F(__is_unbounded_array(short))];
+  int t21[F(__is_unbounded_array(unsigned short))];
+  int t22[F(__is_unbounded_array(int))];
+  int t23[F(__is_unbounded_array(unsigned int))];
+  int t24[F(__is_unbounded_array(long))];
+  int t25[F(__is_unbounded_array(unsigned long))];
+  int t26[F(__is_unbounded_array(Union))];
+  int t27[F(__is_unbounded_array(Derives))];
+  int t28[F(__is_unbounded_array(ClassType))];
+  int t29[F(__is_unbounded_array(Enum))];
+  int t30[F(__is_unbounded_array(void *))];
+  int t31[F(__is_unbounded_array(cvoid *))];
+
+  int t32[n];
+  (void)__is_unbounded_array(decltype(t32)); // expected-error{{variable length arrays are not supported for '__is_unbounded_array'}}
+}
+
+void is_referenceable() {
+  { int a[T(__is_referenceable(int)

[PATCH] D130867: [clang] adds builtin `std::invoke` and `std::invoke_r`

2022-08-06 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb updated this revision to Diff 450587.
cjdb added a comment.

rebases to ToT


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130867

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/Builtins.def
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/ExprConstant.cpp
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/test/SemaCXX/builtin-std-invoke.cpp

Index: clang/test/SemaCXX/builtin-std-invoke.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/builtin-std-invoke.cpp
@@ -0,0 +1,496 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+
+namespace std {
+template 
+void invoke(F &&, Args &&...); // expected-note{{requires at least 1 argument, but 0 were provided}}
+
+template 
+R invoke_r(F &&, Args &&...); // expected-note{{requires at least 1 argument, but 0 were provided}}
+
+// Slightly different to the real deal to simplify test.
+template 
+class reference_wrapper {
+public:
+  constexpr reference_wrapper(T &t) : data(&t) {}
+
+  constexpr operator T &() const noexcept { return *data; }
+
+private:
+  T *data;
+};
+} // namespace std
+
+#define assert(...)   \
+  if (!(__VA_ARGS__)) \
+__builtin_unreachable();
+
+struct ThrowingInt {
+  constexpr ThrowingInt(int x) : value(x) {}
+
+  int value;
+};
+
+template 
+constexpr void bullet_1(F f, T &&t, Args... args) {
+  assert(std::invoke(f, static_cast(t), args...) == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke(f, static_cast(t), args...)), Returns));
+  static_assert(noexcept(std::invoke(f, static_cast(t), args...)) == IsNoexcept);
+
+  assert(std::invoke_r(f, static_cast(t), args...) == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke_r(f, static_cast(t), args...)), double));
+  static_assert(noexcept(std::invoke_r(f, static_cast(t), args...)) == IsNoexcept);
+
+  assert(std::invoke_r(f, static_cast(t), args...).value == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke_r(f, static_cast(t), args...)), ThrowingInt));
+  static_assert(!noexcept(std::invoke_r(f, static_cast(t), args...)));
+}
+
+template 
+constexpr void bullet_2(F f, T &t, Args... args) {
+  std::reference_wrapper rw(t);
+  assert(std::invoke(f, rw, args...) == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke(f, rw, args...)), Returns));
+  static_assert(noexcept(std::invoke(f, rw, args...)) == IsNoexcept);
+
+  assert(std::invoke_r(f, rw, args...) == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke_r(f, rw, args...)), double));
+  static_assert(noexcept(std::invoke_r(f, rw, args...)) == IsNoexcept);
+
+  assert(std::invoke_r(f, rw, args...).value == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke_r(f, rw, args...)), ThrowingInt));
+  static_assert(!noexcept(std::invoke_r(f, rw, args...)));
+}
+
+template 
+class PointerWrapper {
+public:
+  constexpr explicit PointerWrapper(T &t) noexcept : p(&t) {}
+
+  constexpr T &operator*() const noexcept { return *p; }
+
+private:
+  T *p;
+};
+
+template 
+constexpr void bullet_3(F f, T &t, Args... args) {
+  assert(std::invoke(f, &t, args...) == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke(f, &t, args...)), Returns));
+  static_assert(noexcept(std::invoke(f, &t, args...)) == IsNoexcept);
+
+  assert(std::invoke(f, PointerWrapper(t), args...) == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke(f, PointerWrapper(t), args...)), Returns));
+  static_assert(noexcept(std::invoke(f, PointerWrapper(t), args...)) == IsNoexcept);
+
+  assert(std::invoke_r(f, &t, args...) == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke_r(f, &t, args...)), double));
+  static_assert(noexcept(std::invoke_r(f, &t, args...)) == IsNoexcept);
+
+  assert(std::invoke_r(f, PointerWrapper(t), args...) == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke_r(f, PointerWrapper(t), args...)), double));
+  static_assert(noexcept(std::invoke_r(f, PointerWrapper(t), args...)) == IsNoexcept);
+
+  assert(std::invoke_r(f, &t, args...).value == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke_r(f, &t, args...)), ThrowingInt));
+  static_assert(!noexcept(std::invoke_r(f, &t, args...)));
+
+  assert(std::invoke_r(f, PointerWrapper(t), args...).value == ExpectedResult);
+  static_assert(__is_same(decltype(std::invoke_r(f, PointerWrapper(t), args...)), ThrowingInt));
+  static_assert(!noexcept(std::invoke_r(f, PointerWrapper(t), args...)));
+}
+
+template 
+constexpr bool bullets_1_through_3(T t) {
+  bullet_1(&T::plus, t, 3, -3);
+  bullet_1(&T::minus, static_cast(t), 1, 2, 3);
+  bullet_1(&T::square, static_cast<__remove_reference(T) &&>(t), 7

[PATCH] D130867: [clang] adds builtin `std::invoke` and `std::invoke_r`

2022-08-07 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added inline comments.



Comment at: clang/lib/Sema/SemaExprCXX.cpp:5726-5731
+  FirstArgType = S.BuiltinAddReference(
+  dyn_cast(
+  dyn_cast(FirstArgType)->getNamedType())
+  ->getArg(0)
+  .getAsType(),
+  Sema::UTTKind::AddLvalueReference, {});




Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130867

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


[PATCH] D128372: [Clang-Tidy] Empty Check

2022-08-08 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added inline comments.



Comment at: 
clang-tools-extra/clang-tidy/bugprone/StandaloneEmptyCheck.cpp:177-178
+  diag(NonMemberLoc, "ignoring the result of '%0', did you mean 
'clear()'?")
+  << llvm::dyn_cast(NonMemberCall->getCalleeDecl())
+ ->getQualifiedNameAsString()
+  << FixItHint::CreateReplacement(ReplacementRange, ReplacementText);

abrahamcd wrote:
> njames93 wrote:
> > Diagnostics can accept args as `const NamedDecl *`, so you can omit the 
> > call to `getQualifiedNameAsString()`.
> > The use of `dyn_cast` here is suspicious. If the CalleeDecl isn't a 
> > `NamedDecl`, this would assert when you try and call 
> > `getQualifiedNameAsString`, but equally I can't see any case why the 
> > CalleeDecl wouldn't be a `NamedDecl`. @rsmith Can you think of any 
> > situation where this could happen?
> Seems that without `getQualifiedNameAsString()` I get longer less-readable 
> versions of the name, e.g. `'empty &>'` instead of just 
> `'std::empty'`. Do you think the extra information is helpful here?
I'm partial to `'std::empty'` because that's presumably what the user will 
type, and so it'll be easier for them to understand. `'empty 
&>'` isn't useful because we almost always defer to type deduction.



Comment at: clang-tools-extra/clang-tidy/bugprone/StandaloneEmptyCheck.cpp:57-72
+  using ast_matchers::callee;
+  using ast_matchers::callExpr;
+  using ast_matchers::cxxMemberCallExpr;
+  using ast_matchers::cxxMethodDecl;
+  using ast_matchers::expr;
+  using ast_matchers::functionDecl;
+  using ast_matchers::hasName;

njames93 wrote:
> These using declarations are annoying, the common convention in tidy checks 
> is to just use a global `using namespace ast_matchers` at the top of the file.
Adding them just after the namespaces are opened would be good.

I've had issues with refactoring llvm-project files in the past that have 
global //using-directives//, so I'd prefer it if we stuck with the 
//using-declarations// please. If they're a part of the preamble, they become 
additional lines that will be scrolled over.



Comment at: 
clang-tools-extra/clang-tidy/bugprone/StandaloneEmptyCheck.cpp:120-121
+llvm::find_if(Methods, [](const CXXMethodDecl *F) {
+  return F->getDeclName().getAsString() == "clear" &&
+ F->getMinRequiredArguments() == 0;
+});

njames93 wrote:
> We also need to check qualifiers. If there exists a clear method but its 
> unavailable due to it not being const when our member is const. The fix would 
> result in a compile error.
Good catch. We probably shouldn't be suggesting `clear()` on a const object 
anyway.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D128372

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


[PATCH] D130894: [clang] Print more information about failed static assertions

2022-08-09 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb accepted this revision.
cjdb added a comment.
This revision is now accepted and ready to land.

In D130894#3709431 , @aaron.ballman 
wrote:

> In D130894#3709027 , @tbaeder wrote:
>
>> I don't really want to bike-shed about the presentation for too long...
>
> I understand the desire, but at the same time, the whole goal of this patch 
> is to improve the presentation of the diagnostic. You can't invite us all to 
> a bikeshed painting party and then ask us not to use our brushes, that's just 
> cruel! :-D

Agreed. Getting the presentation of diagnostics right is critical.

>> I'm fine with just removing the parens, since we present it like that in the 
>> error message as well anyway:
>>
>>   ./assert.cpp:6:1: error: static assertion failed due to requirement ''c' 
>> == 'a''
>>   static_assert('c' == 'a')
>
> That's still my preference as well. Splitting across multiple lines with hard 
> line breaks has some issues for some IDEs that want to display diagnostic 
> information in a listbox (IIRC), so I'd rather we avoid ad hoc use of line 
> breaks in diagnostics for the moment (it'd be easier/more appropriate if we 
> were making a diagnostic policy for using multiple lines, but that'd involve 
> an RFC and is more effort than I think is needed for this patch).

Fair enough, no further objections on my part.

>>> Any tests with macros?
>>
>> I can add some, but they should be handled transparently, with the usual 
>> "expanded from macro" note.
>
> I'm fine either way.




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

https://reviews.llvm.org/D130894

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


[PATCH] D104887: [clang] Evaluate strlen of strcpy argument for -Wfortify-source.

2021-07-15 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added a comment.

Thanks for getting around to this! Just a nit and a clarifying question.




Comment at: clang/include/clang/Basic/DiagnosticSemaKinds.td:821
+  "'%0' will always overflow; destination buffer has size %1,"
+  " but the source string has length %2 (including null byte)">,
+  InGroup;

Nit: s/null/NUL



Comment at: clang/lib/AST/ExprConstant.cpp:15737
+
+// Fall through to slow path.
+  }

This comment is slightly different to the RHS: does that mean that a diagnostic 
might not be issued?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D104887

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


[PATCH] D102728: [clang][Sema] removes -Wfree-nonheap-object reference param false positive

2021-07-19 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb updated this revision to Diff 360016.
cjdb added a comment.

rebases to activate CI


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D102728

Files:
  clang/lib/Sema/SemaChecking.cpp
  clang/test/Sema/warn-free-nonheap-object.cpp
  mlir/lib/IR/OperationSupport.cpp

Index: mlir/lib/IR/OperationSupport.cpp
===
--- mlir/lib/IR/OperationSupport.cpp
+++ mlir/lib/IR/OperationSupport.cpp
@@ -237,9 +237,7 @@
   if (isDynamicStorage()) {
 TrailingOperandStorage &storage = getDynamicStorage();
 storage.~TrailingOperandStorage();
-// Workaround false positive in -Wfree-nonheap-object
-auto *mem = &storage;
-free(mem);
+free(&storage);
   } else {
 getInlineStorage().~TrailingOperandStorage();
   }
@@ -373,11 +371,8 @@
 new (&newOperands[numOperands]) OpOperand(owner);
 
   // If the current storage is also dynamic, free it.
-  if (isDynamicStorage()) {
-// Workaround false positive in -Wfree-nonheap-object
-auto *mem = &storage;
-free(mem);
-  }
+  if (isDynamicStorage())
+free(&storage);
 
   // Update the storage representation to use the new dynamic storage.
   dynamicStorage.setPointerAndInt(newStorage, true);
Index: clang/test/Sema/warn-free-nonheap-object.cpp
===
--- clang/test/Sema/warn-free-nonheap-object.cpp
+++ clang/test/Sema/warn-free-nonheap-object.cpp
@@ -10,23 +10,34 @@
 
 int GI;
 
+void free_reference(char &x) { ::free(&x); }
+void free_reference(char &&x) { ::free(&x); }
+void std_free_reference(char &x) { std::free(&x); }
+void std_free_reference(char &&x) { std::free(&x); }
+
 struct S {
-  operator char *() { return ptr; }
+  operator char *() { return ptr1; }
 
   void CFree() {
-::free(&ptr); // expected-warning {{attempt to call free on non-heap object 'ptr'}}
-::free(&I);   // expected-warning {{attempt to call free on non-heap object 'I'}}
-::free(ptr);
+::free(&ptr1); // expected-warning {{attempt to call free on non-heap object 'ptr1'}}
+::free(&I);// expected-warning {{attempt to call free on non-heap object 'I'}}
+::free(ptr1);
+free_reference(*ptr2);
+free_reference(static_cast(*ptr3));
   }
 
   void CXXFree() {
-std::free(&ptr); // expected-warning {{attempt to call std::free on non-heap object 'ptr'}}
-std::free(&I);   // expected-warning {{attempt to call std::free on non-heap object 'I'}}
-std::free(ptr);
+std::free(&ptr1); // expected-warning {{attempt to call std::free on non-heap object 'ptr1'}}
+std::free(&I);// expected-warning {{attempt to call std::free on non-heap object 'I'}}
+std::free(ptr1);
+std_free_reference(*ptr2);
+std_free_reference(static_cast(*ptr3));
   }
 
 private:
-  char *ptr = (char *)std::malloc(10);
+  char *ptr1 = (char *)std::malloc(10);
+  char *ptr2 = (char *)std::malloc(10);
+  char *ptr3 = (char *)std::malloc(10);
   static int I;
 };
 
@@ -93,6 +104,14 @@
 void *P = std::malloc(8);
 std::free(P);
   }
+  {
+char* P = (char *)std::malloc(2);
+std_free_reference(*P);
+  }
+  {
+char* P = (char *)std::malloc(2);
+std_free_reference(static_cast(*P));
+  }
   {
 int A[] = {0, 1, 2, 3};
 std::free(A); // expected-warning {{attempt to call std::free on non-heap object 'A'}}
Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -10714,8 +10714,9 @@
  const UnaryOperator *UnaryExpr) {
   if (const auto *Lvalue = dyn_cast(UnaryExpr->getSubExpr())) {
 const Decl *D = Lvalue->getDecl();
-if (isa(D))
-  return CheckFreeArgumentsOnLvalue(S, CalleeName, UnaryExpr, D);
+if (isa(D))
+  if (!dyn_cast(D)->getType()->isReferenceType())
+return CheckFreeArgumentsOnLvalue(S, CalleeName, UnaryExpr, D);
   }
 
   if (const auto *Lvalue = dyn_cast(UnaryExpr->getSubExpr()))
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D106394: [clang][pp] adds '#pragma include_instead'

2021-07-20 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb created this revision.
cjdb added reviewers: aaron.ballman, rsmith, gbiv, dblaikie, cor3ntin.
Herald added a reviewer: george.burgess.iv.
Herald added subscribers: usaxena95, kadircet.
cjdb requested review of this revision.
Herald added subscribers: cfe-commits, ilya-biryukov.
Herald added a project: clang.

`#pragma clang include_instead()` is a pragma that can be used
by system headers (and only system headers) to indicate to a tool that
the file containing said pragma is an implementation-detail header and
should not be directly included by user code.

The library alternative is very messy code that can be seen in the first
diff of D106124 , and we'd rather avoid that 
with something more
universal.

This patch takes the first step by warning a user when they include a
detail header in their code, and suggests alternative headers that the
user should include instead. Future work will involve adding a fixit to
automate the process, as well as cleaning up modules diagnostics to not
suggest said detail headers. Other tools, such as clangd can also take
advantage of this pragma to add the correct user headers.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D106394

Files:
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticLexKinds.td
  clang/include/clang/Lex/HeaderSearch.h
  clang/include/clang/Lex/Preprocessor.h
  clang/include/clang/Lex/PreprocessorLexer.h
  clang/lib/Lex/PPDirectives.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Lex/Pragma.cpp
  clang/test/Preprocessor/Inputs/include_instead/include_instead-bad-syntax.h
  
clang/test/Preprocessor/Inputs/include_instead/include_instead-non-system-header.h
  clang/test/Preprocessor/Inputs/include_instead/include_instead-nowarn.h
  
clang/test/Preprocessor/Inputs/include_instead/include_instead-warns-three-alternatives.h
  
clang/test/Preprocessor/Inputs/include_instead/include_instead-warns-two-alternatives.h
  clang/test/Preprocessor/Inputs/include_instead/include_instead-warns.h
  clang/test/Preprocessor/Inputs/include_instead/malloc.h
  clang/test/Preprocessor/include_instead.cpp

Index: clang/test/Preprocessor/include_instead.cpp
===
--- /dev/null
+++ clang/test/Preprocessor/include_instead.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -I %S/Inputs/include_instead %s
+
+#include 
+#include 
+
+#include 
+// expected-warning@-1{{header '' is an implementation detail; #include '' instead}}
+
+#include "include_instead-warns-two-alternatives.h"
+// expected-warning@-1{{header '"include_instead-warns-two-alternatives.h"' is an implementation detail; #include either '"include_instead-nowarn.h"' or '' instead}}
+
+#include 
+// expected-warning@-1{{header '' is an implementation detail; #include one of {'"include_instead-nowarn.h"', '"include_instead-warns-two-alternatives.h"', ''} instead}}
+
+#include 
Index: clang/test/Preprocessor/Inputs/include_instead/malloc.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/malloc.h
@@ -0,0 +1 @@
+// This file simply needs to exist.
Index: clang/test/Preprocessor/Inputs/include_instead/include_instead-warns.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/include_instead-warns.h
@@ -0,0 +1,3 @@
+#pragma GCC system_header
+
+#pragma clang include_instead()
Index: clang/test/Preprocessor/Inputs/include_instead/include_instead-warns-two-alternatives.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/include_instead-warns-two-alternatives.h
@@ -0,0 +1,4 @@
+#pragma GCC system_header
+
+#pragma clang include_instead()
+#pragma clang include_instead("include_instead-nowarn.h")
Index: clang/test/Preprocessor/Inputs/include_instead/include_instead-warns-three-alternatives.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/include_instead-warns-three-alternatives.h
@@ -0,0 +1,5 @@
+#pragma GCC system_header
+
+#pragma clang include_instead()
+#pragma clang include_instead("include_instead-nowarn.h")
+#pragma clang include_instead("include_instead-warns-two-alternatives.h")
Index: clang/test/Preprocessor/Inputs/include_instead/include_instead-nowarn.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/include_instead-nowarn.h
@@ -0,0 +1,3 @@
+#pragma GCC system_header
+
+#include  // no warning expected
Index: clang/test/Preprocessor/Inputs/include_instead/include_instead-non-system-header.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/include_instead-n

[PATCH] D106394: [clang][pp] adds '#pragma include_instead'

2021-07-20 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added inline comments.



Comment at: clang/lib/Lex/PPLexerChange.cpp:437
+ diag::pp_pragma_include_instead_system_reserved)
+<< Filename << 2 << ('{' + Aliases + '}');
+  }

I wasn't able to work out how to escape braces inside diagnostic files. Seems 
neither `{{` nor `\{` work :(


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D106394

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


[PATCH] D106394: [clang][pp] adds '#pragma include_instead'

2021-07-20 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added a comment.

In D106394#2891647 , @zoecarver wrote:

> Can't wait to start using this! (Note: this is not a full review, just some 
> thoughts.)
>
> Do you have a test case where
>
>   // private: header one
>   *exists*
>   
>   // private: header two
>   #include<__header_one.h>
>   
>   // public: header three
>   #include<__header_two.h>
>
> I think right now you might see a warning that says "please include either 
> `__header_two.h` or `header_three.h`" which is not right.

Right now, I've got `please include either '' or 
'"publich_header_2.h"'` and `please include one of {'', 
'"publich_header_2.h"', ''}`. I suppose I should add 
another public header.

> This begs the question, would it not be better to have a second argument that 
> specifies what header should be used as a replacement? This would also allow 
> the person writing the library to decide whether it's better to use angle 
> brackets or quotes.

This is the purpose of the first argument, so I'm not sure I follow.




Comment at: clang/include/clang/Lex/HeaderSearch.h:465
+getFileInfo(File).Aliases;
+auto InsertionPoint = llvm::lower_bound(Aliases, Alias);
+if (InsertionPoint != Aliases.end() && *InsertionPoint == Alias)

zoecarver wrote:
> Is the logic here is just "if it's not already here add it?" If so, I think 
> maybe you should just make `Aliases` a set (either a `StringSet` or 
> `SmallSet`). Do you care about order? 
Yes. I was going to use `StringSet`, but need `operator[]` for diagnostics. 
`SetVector` was my next choice, but it was giving me some serious complaints 
about a `DeepMap` or something. I guess I could copy the `StringSet`'s contents 
into a `SmallVector` at the diagnostic site, but I really don't expect headers 
to have more than two aliases?



Comment at: clang/lib/Lex/PPLexerChange.cpp:429
+};
+std::string Aliases =
+std::accumulate(Info.Aliases.begin() + 1, Info.Aliases.end(),

zoecarver wrote:
> Can we use `llvm::interleaveComma` or `interleave`?
Thanks, I was looking for `join`!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D106394

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


[PATCH] D106394: [clang][pp] adds '#pragma include_instead'

2021-07-20 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb updated this revision to Diff 360317.
cjdb marked an inline comment as done.
cjdb added a comment.

- renames test files so they better describe intention
- replaces `SmallVector` with `SetVector`
- replaces `std::accumulate` with `llvm::interleave`


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D106394

Files:
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticLexKinds.td
  clang/include/clang/Lex/HeaderSearch.h
  clang/include/clang/Lex/Preprocessor.h
  clang/include/clang/Lex/PreprocessorLexer.h
  clang/lib/Lex/PPDirectives.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Lex/Pragma.cpp
  clang/test/Preprocessor/Inputs/include_instead/include_instead-bad-syntax.h
  
clang/test/Preprocessor/Inputs/include_instead/include_instead-non-system-header.h
  
clang/test/Preprocessor/Inputs/include_instead/include_instead-warns-one-alternative.h
  
clang/test/Preprocessor/Inputs/include_instead/include_instead-warns-three-alternatives.h
  
clang/test/Preprocessor/Inputs/include_instead/include_instead-warns-two-alternatives.h
  clang/test/Preprocessor/Inputs/include_instead/public1.h
  clang/test/Preprocessor/Inputs/include_instead/public2.h
  clang/test/Preprocessor/Inputs/include_instead/public3.h
  clang/test/Preprocessor/include_instead.cpp

Index: clang/test/Preprocessor/include_instead.cpp
===
--- /dev/null
+++ clang/test/Preprocessor/include_instead.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -I %S/Inputs/include_instead %s
+
+#include 
+#include 
+
+#include 
+// expected-warning@-1{{header '' is an implementation detail; #include '' instead}}
+
+#include "include_instead-warns-two-alternatives.h"
+// expected-warning@-1{{header '"include_instead-warns-two-alternatives.h"' is an implementation detail; #include either '' or '"public2.h"' instead}}
+
+#include 
+// expected-warning@-1{{header '' is an implementation detail; #include one of {'', '', '"public2.h"'} instead}}
+
+#include 
+#include 
+#include 
Index: clang/test/Preprocessor/Inputs/include_instead/public3.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public3.h
@@ -0,0 +1 @@
+// This file simply needs to exist.
Index: clang/test/Preprocessor/Inputs/include_instead/public2.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public2.h
@@ -0,0 +1 @@
+// This file simply needs to exist.
Index: clang/test/Preprocessor/Inputs/include_instead/public1.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public1.h
@@ -0,0 +1,5 @@
+#pragma GCC system_header
+
+#include  // no warning expected
+#include  // no warning expected
+#include  // no warning expected
Index: clang/test/Preprocessor/Inputs/include_instead/include_instead-warns-two-alternatives.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/include_instead-warns-two-alternatives.h
@@ -0,0 +1,4 @@
+#pragma GCC system_header
+
+#pragma clang include_instead()
+#pragma clang include_instead("public2.h")
Index: clang/test/Preprocessor/Inputs/include_instead/include_instead-warns-three-alternatives.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/include_instead-warns-three-alternatives.h
@@ -0,0 +1,5 @@
+#pragma GCC system_header
+
+#pragma clang include_instead()
+#pragma clang include_instead() // deliberately not sorted
+#pragma clang include_instead("public2.h")
Index: clang/test/Preprocessor/Inputs/include_instead/include_instead-warns-one-alternative.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/include_instead-warns-one-alternative.h
@@ -0,0 +1,3 @@
+#pragma GCC system_header
+
+#pragma clang include_instead()
Index: clang/test/Preprocessor/Inputs/include_instead/include_instead-non-system-header.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/include_instead-non-system-header.h
@@ -0,0 +1,2 @@
+#pragma clang include_instead()
+// expected-warning@-1{{'#pragma include_instead' ignored outside of system headers}}
Index: clang/test/Preprocessor/Inputs/include_instead/include_instead-bad-syntax.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/include_instead-bad-syntax.h
@@ -0,0 +1,10 @@
+#pragma GCC system_header
+
+#pragma clang include_instead 
+// expected-warning@-1{{'#pragma include_instead' expects '(' as its 

[PATCH] D106394: [clang][pp] adds '#pragma include_instead'

2021-07-21 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added a comment.

In D106394#2892832 , @sammccall wrote:

> This is pretty interesting from a tooling perspective!
>
> Some prior art here are the include-what-you-use "pragmas" 
> 
>  (magic comments). Clangd supports `// IWYU pragma: "private", include 
> "public.h"` which has similar semantics to that proposed here.
>
> Having multiple alternatives makes this less useful to tools as it's 
> ambiguous what the correct action/fix is. It's necessary for the standard 
> library and the syntax doesn't really encourage it, so that seems OK. Worst 
> case, tools can ignore the pragmas when several are present.

Hmm... I like prior art. That clangd supports it suggests that there's a 
section of code I can look at for inspiration if we were to replace this pragma 
with the IWYU comment-pragma (I wonder why they didn't just go with `#pragma 
IWYU ...`?).

Is it reasonable for a compiler to interpret comments and issue/adjust 
diagnostics based on those comments? I thought that was the purpose of a 
pp-pragma.

> Eventually this seems like a reasonable thing to want for user code. What are 
> your motivations for restricting it to system headers? (And do you think 
> people in future will be tempted to lift them?)
> FWIW in the short term in clangd it's not that useful for the standard 
> libraries, as we can enumerate all the symbols and that will work with 
> libstdc+, MS stdlib...
>
> For user code it's worth thinking about how the alternatives are specified - 
> in the standard library a literal string `` is correct, but in user 
> code you may rather want a path to the correct *file* (relative to the 
> current file) which can then be turned into a spelled `#include` according to 
> the including file's header search path.

Louis' answer is wholesale correct, at least for now. If someone wants to 
extend the design to support "groups", then I'll happily consider the design; 
that's not something I've been able to provide a trivial solution to (it 
usually just comes back to redesigning `-fmodules`).


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D106394

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


[PATCH] D106394: [clang][pp] adds '#pragma include_instead'

2021-07-21 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb updated this revision to Diff 360519.
cjdb added a comment.

- renames files
- makes it possible for `#pragma GCC system_header` to come after includes


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D106394

Files:
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticLexKinds.td
  clang/include/clang/Lex/HeaderSearch.h
  clang/include/clang/Lex/Preprocessor.h
  clang/include/clang/Lex/PreprocessorLexer.h
  clang/lib/Lex/Lexer.cpp
  clang/lib/Lex/PPDirectives.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Lex/Pragma.cpp
  clang/test/Preprocessor/Inputs/include_instead/bad-syntax.h
  clang/test/Preprocessor/Inputs/include_instead/non-system-header.h
  clang/test/Preprocessor/Inputs/include_instead/private-x.h
  clang/test/Preprocessor/Inputs/include_instead/private1.h
  clang/test/Preprocessor/Inputs/include_instead/private2.h
  clang/test/Preprocessor/Inputs/include_instead/private3.h
  clang/test/Preprocessor/Inputs/include_instead/public-after.h
  clang/test/Preprocessor/Inputs/include_instead/public-before.h
  clang/test/Preprocessor/Inputs/include_instead/public-empty.h
  clang/test/Preprocessor/include_instead.cpp

Index: clang/test/Preprocessor/include_instead.cpp
===
--- /dev/null
+++ clang/test/Preprocessor/include_instead.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -I %S/Inputs %s
+
+#include 
+#include 
+
+#include 
+// expected-warning@-1{{header '' is an implementation detail; #include '' instead}}
+
+#include "include_instead/private2.h"
+// expected-warning@-1{{header '"include_instead/private2.h"' is an implementation detail; #include either '' or '"include_instead/public-after.h"' instead}}
+
+#include 
+// expected-warning@-1{{header '' is an implementation detail; #include one of {'', '', '"include_instead/public-before.h"'} instead}}
+
+#include 
+#include 
Index: clang/test/Preprocessor/Inputs/include_instead/public-empty.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public-empty.h
@@ -0,0 +1 @@
+// This file simply needs to exist.
Index: clang/test/Preprocessor/Inputs/include_instead/public-before.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public-before.h
@@ -0,0 +1,5 @@
+#pragma GCC system_header
+
+#include  // no warning expected
+#include  // no warning expected
+#include  // no warning expected
Index: clang/test/Preprocessor/Inputs/include_instead/public-after.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public-after.h
@@ -0,0 +1,2 @@
+#include 
+#pragma GCC system_header
Index: clang/test/Preprocessor/Inputs/include_instead/private3.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private3.h
@@ -0,0 +1,5 @@
+#pragma GCC system_header
+
+#pragma clang include_instead()
+#pragma clang include_instead()
+#pragma clang include_instead("include_instead/public-before.h")
Index: clang/test/Preprocessor/Inputs/include_instead/private2.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private2.h
@@ -0,0 +1,4 @@
+#pragma GCC system_header
+
+#pragma clang include_instead()
+#pragma clang include_instead("include_instead/public-after.h")
Index: clang/test/Preprocessor/Inputs/include_instead/private1.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private1.h
@@ -0,0 +1,2 @@
+#pragma GCC system_header
+#pragma clang include_instead()
Index: clang/test/Preprocessor/Inputs/include_instead/private-x.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private-x.h
@@ -0,0 +1,4 @@
+#include 
+
+#pragma GCC system_header
+#pragma clang include_instead()
Index: clang/test/Preprocessor/Inputs/include_instead/non-system-header.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/non-system-header.h
@@ -0,0 +1,2 @@
+#pragma clang include_instead()
+// expected-warning@-1{{'#pragma include_instead' ignored outside of system headers}}
Index: clang/test/Preprocessor/Inputs/include_instead/bad-syntax.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/bad-syntax.h
@@ -0,0 +1,10 @@
+#pragma GCC system_header
+
+#pragma clang include_instead 
+// expected-warning@-1{{'#pragma include_instead' expects '(' as its next token; got '<' instead}}
+

[PATCH] D106394: [clang][pp] adds '#pragma include_instead'

2021-07-21 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added a comment.

In D106394#2893681 , @Quuxplusone 
wrote:

> If IWYU has already developed a de facto standard for this information, I 
> would recommend libc++ just use it (perhaps with no changes needed in clang 
> at all). This would have the benefit of getting libc++ to work with IWYU 
> out-of-the-box, instead of having to go beg IWYU to implement support for a 
> new `#pragma include_instead`.  Is any IWYU developer aware of D106394 
>  yet? You should definitely try to get them 
> involved here.

This suggestion misses the fact that this change issues a warning to users who 
include detail system headers and the fact that Clang can use this to improve 
its diagnostics.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D106394

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


[PATCH] D102728: [clang][Sema] removes -Wfree-nonheap-object reference param false positive

2021-07-21 Thread Christopher Di Bella 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 rG9a72580a548d: [clang][Sema] removes -Wfree-nonheap-object 
reference param false positive (authored by cjdb).

Changed prior to commit:
  https://reviews.llvm.org/D102728?vs=360016&id=360602#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D102728

Files:
  clang/lib/Sema/SemaChecking.cpp
  clang/test/Sema/warn-free-nonheap-object.cpp


Index: clang/test/Sema/warn-free-nonheap-object.cpp
===
--- clang/test/Sema/warn-free-nonheap-object.cpp
+++ clang/test/Sema/warn-free-nonheap-object.cpp
@@ -10,23 +10,34 @@
 
 int GI;
 
+void free_reference(char &x) { ::free(&x); }
+void free_reference(char &&x) { ::free(&x); }
+void std_free_reference(char &x) { std::free(&x); }
+void std_free_reference(char &&x) { std::free(&x); }
+
 struct S {
-  operator char *() { return ptr; }
+  operator char *() { return ptr1; }
 
   void CFree() {
-::free(&ptr); // expected-warning {{attempt to call free on non-heap 
object 'ptr'}}
-::free(&I);   // expected-warning {{attempt to call free on non-heap 
object 'I'}}
-::free(ptr);
+::free(&ptr1); // expected-warning {{attempt to call free on non-heap 
object 'ptr1'}}
+::free(&I);// expected-warning {{attempt to call free on non-heap 
object 'I'}}
+::free(ptr1);
+free_reference(*ptr2);
+free_reference(static_cast(*ptr3));
   }
 
   void CXXFree() {
-std::free(&ptr); // expected-warning {{attempt to call std::free on 
non-heap object 'ptr'}}
-std::free(&I);   // expected-warning {{attempt to call std::free on 
non-heap object 'I'}}
-std::free(ptr);
+std::free(&ptr1); // expected-warning {{attempt to call std::free on 
non-heap object 'ptr1'}}
+std::free(&I);// expected-warning {{attempt to call std::free on 
non-heap object 'I'}}
+std::free(ptr1);
+std_free_reference(*ptr2);
+std_free_reference(static_cast(*ptr3));
   }
 
 private:
-  char *ptr = (char *)std::malloc(10);
+  char *ptr1 = (char *)std::malloc(10);
+  char *ptr2 = (char *)std::malloc(10);
+  char *ptr3 = (char *)std::malloc(10);
   static int I;
 };
 
@@ -93,6 +104,14 @@
 void *P = std::malloc(8);
 std::free(P);
   }
+  {
+char* P = (char *)std::malloc(2);
+std_free_reference(*P);
+  }
+  {
+char* P = (char *)std::malloc(2);
+std_free_reference(static_cast(*P));
+  }
   {
 int A[] = {0, 1, 2, 3};
 std::free(A); // expected-warning {{attempt to call std::free on non-heap 
object 'A'}}
Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -10726,8 +10726,9 @@
  const UnaryOperator *UnaryExpr) {
   if (const auto *Lvalue = dyn_cast(UnaryExpr->getSubExpr())) {
 const Decl *D = Lvalue->getDecl();
-if (isa(D))
-  return CheckFreeArgumentsOnLvalue(S, CalleeName, UnaryExpr, D);
+if (isa(D))
+  if (!dyn_cast(D)->getType()->isReferenceType())
+return CheckFreeArgumentsOnLvalue(S, CalleeName, UnaryExpr, D);
   }
 
   if (const auto *Lvalue = dyn_cast(UnaryExpr->getSubExpr()))


Index: clang/test/Sema/warn-free-nonheap-object.cpp
===
--- clang/test/Sema/warn-free-nonheap-object.cpp
+++ clang/test/Sema/warn-free-nonheap-object.cpp
@@ -10,23 +10,34 @@
 
 int GI;
 
+void free_reference(char &x) { ::free(&x); }
+void free_reference(char &&x) { ::free(&x); }
+void std_free_reference(char &x) { std::free(&x); }
+void std_free_reference(char &&x) { std::free(&x); }
+
 struct S {
-  operator char *() { return ptr; }
+  operator char *() { return ptr1; }
 
   void CFree() {
-::free(&ptr); // expected-warning {{attempt to call free on non-heap object 'ptr'}}
-::free(&I);   // expected-warning {{attempt to call free on non-heap object 'I'}}
-::free(ptr);
+::free(&ptr1); // expected-warning {{attempt to call free on non-heap object 'ptr1'}}
+::free(&I);// expected-warning {{attempt to call free on non-heap object 'I'}}
+::free(ptr1);
+free_reference(*ptr2);
+free_reference(static_cast(*ptr3));
   }
 
   void CXXFree() {
-std::free(&ptr); // expected-warning {{attempt to call std::free on non-heap object 'ptr'}}
-std::free(&I);   // expected-warning {{attempt to call std::free on non-heap object 'I'}}
-std::free(ptr);
+std::free(&ptr1); // expected-warning {{attempt to call std::free on non-heap object 'ptr1'}}
+std::free(&I);// expected-warning {{attempt to call std::free on non-heap object 'I'}}
+std::free(ptr1);
+std_free_reference(*ptr2);
+std_free_reference(static_cast(*ptr3));
   }
 
 private:
-  char *ptr = (char *)std::malloc

[PATCH] D106394: [clang][pp] adds '#pragma include_instead'

2021-07-22 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added a comment.

Thanks for the first pass @aaron.ballman! Some clarifying questions, but I 
think I have enough of your other comments to work on while you ponder these.




Comment at: clang/include/clang/Basic/DiagnosticLexKinds.td:303
   InGroup>;
+def pp_pragma_include_instead_not_sysheader : Warning<
+  "'#pragma include_instead' ignored outside of system headers">,

aaron.ballman wrote:
> Design-wise, do we want this one to be an error instead of a warning? I don't 
> have strong feelings one way or the other, but making it an error ensures no 
> one finds creative ways to use it outside of a system header by accident (and 
> we can relax the restriction later if there are reasons to do so).
I'd prefer it to be an error, but I wasn't confident that would be accepted 
(same applies to all your comments re warn vs err). If you're game, I'll make 
the change.



Comment at: clang/include/clang/Basic/DiagnosticLexKinds.td:306
+  InGroup,
+  ShowInSystemHeader;
+def pp_pragma_include_instead_unexpected_token : Warning<

aaron.ballman wrote:
> O.o... why do we need to show this one in system headers if the diagnostic 
> can only trigger outside of a system header?
Mostly because I'm scared that there's some toggle that would accidentally make 
the diagnostic observable in a system header and wanted to test the behaviour.



Comment at: clang/lib/Lex/PPLexerChange.cpp:316
+const StringRef Filename = Include.getKey();
+const auto &IncludeInfo = Include.getValue();
+const HeaderFileInfo &Info = HeaderInfo.getFileInfo(IncludeInfo.File);

aaron.ballman wrote:
> Please spell out the type.
The type's currently a private type (that was by design). Do you want me to 
make it a public type or pull it out into `namespace clang`?



Comment at: clang/lib/Lex/Pragma.cpp:559
+Diag(Tok, diag::pp_pragma_include_instead_unexpected_token)
+<< "(" << (spelling == "\n" ? "\\n" : spelling);
+return;

I thought I deleted this.



Comment at: clang/lib/Lex/Pragma.cpp:572
+  if (Tok.isNot(tok::r_paren)) {
+const std::string spelling = getSpelling(Tok);
+Diag(Tok, diag::pp_pragma_include_instead_unexpected_token)

aaron.ballman wrote:
> 
Alternatively: remove `spelling` altogether.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D106394

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


[PATCH] D106394: [clang][pp] adds '#pragma include_instead'

2021-07-22 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb marked 2 inline comments as done.
cjdb added inline comments.



Comment at: clang/include/clang/Basic/DiagnosticLexKinds.td:307-310
+def pp_pragma_include_instead_unexpected_token : Warning<
+  "'#pragma include_instead' expects '%0' as its next token; got '%1' 
instead">,
+  InGroup,
+  ShowInSystemHeader;

aaron.ballman wrote:
> No need for a new warning -- I think we can use existing diagnostics for this 
> (like `err_pp_expects_filename`). Also, I think syntax issues should be 
> diagnosed as an error instead of a warning -- we expect a particular 
> syntactic form and it's reasonable for us to enforce that users get it right.
Hmm... the syntax is `#pragma clang include_instead(header)`. This is 
diagnosing the lack of `(` or `)`, not a missing filename. Perhaps there's 
already a diagnostic for that?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D106394

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


[PATCH] D106394: [clang][pp] adds '#pragma include_instead'

2021-07-22 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb updated this revision to Diff 361014.
cjdb marked 12 inline comments as done.
cjdb added a comment.

- applies all of @aaron.ballman's suggested changes
- turns warnings into errors and deletes warning group
- replaces `interleave` with `join`
- properly abandons LF transmuting

The only things that shouldn't be applied are comments with replies (and even 
some of those have been actioned).


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D106394

Files:
  clang/include/clang/Basic/DiagnosticLexKinds.td
  clang/include/clang/Lex/HeaderSearch.h
  clang/include/clang/Lex/Preprocessor.h
  clang/include/clang/Lex/PreprocessorLexer.h
  clang/lib/Lex/Lexer.cpp
  clang/lib/Lex/PPDirectives.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Lex/Pragma.cpp
  clang/test/Preprocessor/Inputs/include_instead/bad-syntax.h
  clang/test/Preprocessor/Inputs/include_instead/file-not-found.h
  clang/test/Preprocessor/Inputs/include_instead/non-system-header.h
  clang/test/Preprocessor/Inputs/include_instead/private-x.h
  clang/test/Preprocessor/Inputs/include_instead/private1.h
  clang/test/Preprocessor/Inputs/include_instead/private2.h
  clang/test/Preprocessor/Inputs/include_instead/private3.h
  clang/test/Preprocessor/Inputs/include_instead/public-after.h
  clang/test/Preprocessor/Inputs/include_instead/public-before.h
  clang/test/Preprocessor/Inputs/include_instead/public-empty.h
  clang/test/Preprocessor/include_instead.cpp
  clang/test/Preprocessor/include_instead_file_not_found.cpp

Index: clang/test/Preprocessor/include_instead_file_not_found.cpp
===
--- /dev/null
+++ clang/test/Preprocessor/include_instead_file_not_found.cpp
@@ -0,0 +1,2 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -I %S/Inputs %s
+#include 
Index: clang/test/Preprocessor/include_instead.cpp
===
--- /dev/null
+++ clang/test/Preprocessor/include_instead.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -I %S/Inputs %s
+
+#include 
+#include 
+
+#include 
+// expected-error@-1{{header '' is an implementation detail; #include '' instead}}
+
+#include "include_instead/private2.h"
+// expected-error@-1{{header '"include_instead/private2.h"' is an implementation detail; #include either '' or '"include_instead/public-after.h"' instead}}
+
+#include 
+// expected-error@-1{{header '' is an implementation detail; #include one of {'', '', '"include_instead/public-before.h"'} instead}}
+
+#include 
+#include 
Index: clang/test/Preprocessor/Inputs/include_instead/public-empty.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public-empty.h
@@ -0,0 +1 @@
+// This file simply needs to exist.
Index: clang/test/Preprocessor/Inputs/include_instead/public-before.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public-before.h
@@ -0,0 +1,5 @@
+#pragma GCC system_header
+
+#include  // no warning expected
+#include  // no warning expected
+#include  // no warning expected
Index: clang/test/Preprocessor/Inputs/include_instead/public-after.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public-after.h
@@ -0,0 +1,2 @@
+#include 
+#pragma GCC system_header
Index: clang/test/Preprocessor/Inputs/include_instead/private3.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private3.h
@@ -0,0 +1,5 @@
+#pragma GCC system_header
+
+#pragma clang include_instead()
+#pragma clang include_instead()
+#pragma clang include_instead("include_instead/public-before.h")
Index: clang/test/Preprocessor/Inputs/include_instead/private2.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private2.h
@@ -0,0 +1,4 @@
+#pragma GCC system_header
+
+#pragma clang include_instead()
+#pragma clang include_instead("include_instead/public-after.h")
Index: clang/test/Preprocessor/Inputs/include_instead/private1.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private1.h
@@ -0,0 +1,2 @@
+#pragma GCC system_header
+#pragma clang include_instead()
Index: clang/test/Preprocessor/Inputs/include_instead/private-x.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private-x.h
@@ -0,0 +1,4 @@
+#include 
+
+#pragma GCC system_header
+#pragma clang include_instead()
Index: clang/test/Preprocessor/Inputs/include_instead/non-system-header.h
===
--

[PATCH] D106394: [clang][pp] adds '#pragma include_instead'

2021-07-23 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb updated this revision to Diff 361357.
cjdb marked 11 inline comments as done.
cjdb added a comment.

applies all of @aaron.ballman's remaining feedback


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D106394

Files:
  clang/include/clang/Basic/DiagnosticLexKinds.td
  clang/include/clang/Lex/HeaderSearch.h
  clang/include/clang/Lex/Preprocessor.h
  clang/include/clang/Lex/PreprocessorLexer.h
  clang/lib/Lex/Lexer.cpp
  clang/lib/Lex/PPDirectives.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Lex/Pragma.cpp
  clang/test/Preprocessor/Inputs/include_instead/bad-syntax.h
  clang/test/Preprocessor/Inputs/include_instead/file-not-found.h
  clang/test/Preprocessor/Inputs/include_instead/non-system-header.h
  clang/test/Preprocessor/Inputs/include_instead/private-x.h
  clang/test/Preprocessor/Inputs/include_instead/private1.h
  clang/test/Preprocessor/Inputs/include_instead/private2.h
  clang/test/Preprocessor/Inputs/include_instead/private3.h
  clang/test/Preprocessor/Inputs/include_instead/public-after.h
  clang/test/Preprocessor/Inputs/include_instead/public-before.h
  clang/test/Preprocessor/Inputs/include_instead/public-empty.h
  clang/test/Preprocessor/include_instead.cpp
  clang/test/Preprocessor/include_instead_file_not_found.cpp

Index: clang/test/Preprocessor/include_instead_file_not_found.cpp
===
--- /dev/null
+++ clang/test/Preprocessor/include_instead_file_not_found.cpp
@@ -0,0 +1,2 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -I %S/Inputs %s
+#include 
Index: clang/test/Preprocessor/include_instead.cpp
===
--- /dev/null
+++ clang/test/Preprocessor/include_instead.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -I %S/Inputs %s
+
+#include 
+#include 
+
+#include 
+// expected-error@-1{{header '' is an implementation detail; #include '' instead}}
+
+#include "include_instead/private2.h"
+// expected-error@-1{{header '"include_instead/private2.h"' is an implementation detail; #include either '' or '"include_instead/public-after.h"' instead}}
+
+#include 
+// expected-error@-1{{header '' is an implementation detail; #include one of {'', '', '"include_instead/public-before.h"'} instead}}
+
+#include 
+#include 
Index: clang/test/Preprocessor/Inputs/include_instead/public-empty.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public-empty.h
@@ -0,0 +1 @@
+// This file simply needs to exist.
Index: clang/test/Preprocessor/Inputs/include_instead/public-before.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public-before.h
@@ -0,0 +1,5 @@
+#pragma GCC system_header
+
+#include  // no warning expected
+#include  // no warning expected
+#include  // no warning expected
Index: clang/test/Preprocessor/Inputs/include_instead/public-after.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public-after.h
@@ -0,0 +1,2 @@
+#include 
+#pragma GCC system_header
Index: clang/test/Preprocessor/Inputs/include_instead/private3.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private3.h
@@ -0,0 +1,5 @@
+#pragma GCC system_header
+
+#pragma clang include_instead()
+#pragma clang include_instead()
+#pragma clang include_instead("include_instead/public-before.h")
Index: clang/test/Preprocessor/Inputs/include_instead/private2.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private2.h
@@ -0,0 +1,4 @@
+#pragma GCC system_header
+
+#pragma clang include_instead()
+#pragma clang include_instead("include_instead/public-after.h")
Index: clang/test/Preprocessor/Inputs/include_instead/private1.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private1.h
@@ -0,0 +1,2 @@
+#pragma GCC system_header
+#pragma clang include_instead()
Index: clang/test/Preprocessor/Inputs/include_instead/private-x.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private-x.h
@@ -0,0 +1,4 @@
+#include 
+
+#pragma GCC system_header
+#pragma clang include_instead()
Index: clang/test/Preprocessor/Inputs/include_instead/non-system-header.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/non-system-header.h
@@ -0,0 +1,2 @@
+#pragma clang include_instead()
+// expected-error@-1{{'#pragma clang include_instead' cannot be used outside of system headers}}
Index: clang

[PATCH] D106394: [clang][pp] adds '#pragma include_instead'

2021-07-23 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added inline comments.



Comment at: clang/include/clang/Basic/DiagnosticLexKinds.td:304
+
+def pp_pragma_include_instead_not_sysheader : Error<
+  "'#pragma clang include_instead' cannot be used outside of system headers">,

aaron.ballman wrote:
> Can you prefix the diagnostic identifiers with `err_`? We're not super 
> consistent in this file, but it's helpful when reading the use of the 
> diagnostic to know whether it's an error or not.
I've replaced `pp` with `err` since `pragma` implies "preprocessor" and don't 
really think it adds much more value. `err` on the other hand is useful?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D106394

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


[PATCH] D106252: Implement P2092

2021-07-23 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb accepted this revision.
cjdb added a comment.
This revision is now accepted and ready to land.

LGTM upon inspection. There aren't any cases in libc++ that I'm aware of that 
will break because of this, but I think it's a good practice to try and 
bootstrap the library for certainty.

Please also provide a more descriptive Git commit subject (I don't know what 
P2092  is at a glance).


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D106252

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


[PATCH] D106394: [clang][pp] adds '#pragma include_instead'

2021-07-26 Thread Christopher Di Bella 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 rGe8a64e549126: [clang][pp] adds '#pragma 
include_instead' (authored by cjdb).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D106394

Files:
  clang/include/clang/Basic/DiagnosticLexKinds.td
  clang/include/clang/Lex/HeaderSearch.h
  clang/include/clang/Lex/Preprocessor.h
  clang/include/clang/Lex/PreprocessorLexer.h
  clang/lib/Lex/Lexer.cpp
  clang/lib/Lex/PPDirectives.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Lex/Pragma.cpp
  clang/test/Preprocessor/Inputs/include_instead/bad-syntax.h
  clang/test/Preprocessor/Inputs/include_instead/file-not-found.h
  clang/test/Preprocessor/Inputs/include_instead/non-system-header.h
  clang/test/Preprocessor/Inputs/include_instead/private-x.h
  clang/test/Preprocessor/Inputs/include_instead/private1.h
  clang/test/Preprocessor/Inputs/include_instead/private2.h
  clang/test/Preprocessor/Inputs/include_instead/private3.h
  clang/test/Preprocessor/Inputs/include_instead/public-after.h
  clang/test/Preprocessor/Inputs/include_instead/public-before.h
  clang/test/Preprocessor/Inputs/include_instead/public-empty.h
  clang/test/Preprocessor/include_instead.cpp
  clang/test/Preprocessor/include_instead_file_not_found.cpp

Index: clang/test/Preprocessor/include_instead_file_not_found.cpp
===
--- /dev/null
+++ clang/test/Preprocessor/include_instead_file_not_found.cpp
@@ -0,0 +1,2 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -I %S/Inputs %s
+#include 
Index: clang/test/Preprocessor/include_instead.cpp
===
--- /dev/null
+++ clang/test/Preprocessor/include_instead.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -I %S/Inputs %s
+
+#include 
+#include 
+
+#include 
+// expected-error@-1{{header '' is an implementation detail; #include '' instead}}
+
+#include "include_instead/private2.h"
+// expected-error@-1{{header '"include_instead/private2.h"' is an implementation detail; #include either '' or '"include_instead/public-after.h"' instead}}
+
+#include 
+// expected-error@-1{{header '' is an implementation detail; #include one of {'', '', '"include_instead/public-before.h"'} instead}}
+
+#include 
+#include 
Index: clang/test/Preprocessor/Inputs/include_instead/public-empty.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public-empty.h
@@ -0,0 +1 @@
+// This file simply needs to exist.
Index: clang/test/Preprocessor/Inputs/include_instead/public-before.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public-before.h
@@ -0,0 +1,5 @@
+#pragma GCC system_header
+
+#include  // no warning expected
+#include  // no warning expected
+#include  // no warning expected
Index: clang/test/Preprocessor/Inputs/include_instead/public-after.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public-after.h
@@ -0,0 +1,2 @@
+#include 
+#pragma GCC system_header
Index: clang/test/Preprocessor/Inputs/include_instead/private3.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private3.h
@@ -0,0 +1,5 @@
+#pragma GCC system_header
+
+#pragma clang include_instead()
+#pragma clang include_instead()
+#pragma clang include_instead("include_instead/public-before.h")
Index: clang/test/Preprocessor/Inputs/include_instead/private2.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private2.h
@@ -0,0 +1,4 @@
+#pragma GCC system_header
+
+#pragma clang include_instead()
+#pragma clang include_instead("include_instead/public-after.h")
Index: clang/test/Preprocessor/Inputs/include_instead/private1.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private1.h
@@ -0,0 +1,2 @@
+#pragma GCC system_header
+#pragma clang include_instead()
Index: clang/test/Preprocessor/Inputs/include_instead/private-x.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private-x.h
@@ -0,0 +1,4 @@
+#include 
+
+#pragma GCC system_header
+#pragma clang include_instead()
Index: clang/test/Preprocessor/Inputs/include_instead/non-system-header.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/non-system-header.h
@@ -0,0 +1,2 @@
+#pragma clang include_instead()
+// expected-error@-1{{'#pragma clang inc

[PATCH] D106898: Revert "Revert "[clang][pp] adds '#pragma include_instead'"" Includes regression test for problem noted by @hans.

2021-07-27 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb created this revision.
cjdb added reviewers: aaron.ballman, rsmith, dblaikie.
cjdb requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This reverts commit 973de7185606a21fd5e9d5e8c014fbf898c0e72f 
.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D106898

Files:
  clang/include/clang/Basic/DiagnosticLexKinds.td
  clang/include/clang/Lex/HeaderSearch.h
  clang/include/clang/Lex/Preprocessor.h
  clang/include/clang/Lex/PreprocessorLexer.h
  clang/lib/Lex/Lexer.cpp
  clang/lib/Lex/PPDirectives.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Lex/Pragma.cpp
  clang/test/PCH/ms-pch-macro-include_instead-regression.c
  clang/test/Preprocessor/Inputs/include_instead/bad-syntax.h
  clang/test/Preprocessor/Inputs/include_instead/file-not-found.h
  clang/test/Preprocessor/Inputs/include_instead/non-system-header.h
  clang/test/Preprocessor/Inputs/include_instead/private-x.h
  clang/test/Preprocessor/Inputs/include_instead/private1.h
  clang/test/Preprocessor/Inputs/include_instead/private2.h
  clang/test/Preprocessor/Inputs/include_instead/private3.h
  clang/test/Preprocessor/Inputs/include_instead/public-after.h
  clang/test/Preprocessor/Inputs/include_instead/public-before.h
  clang/test/Preprocessor/Inputs/include_instead/public-empty.h
  clang/test/Preprocessor/include_instead.cpp
  clang/test/Preprocessor/include_instead_file_not_found.cpp

Index: clang/test/Preprocessor/include_instead_file_not_found.cpp
===
--- /dev/null
+++ clang/test/Preprocessor/include_instead_file_not_found.cpp
@@ -0,0 +1,2 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -I %S/Inputs %s
+#include 
Index: clang/test/Preprocessor/include_instead.cpp
===
--- /dev/null
+++ clang/test/Preprocessor/include_instead.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -I %S/Inputs %s
+
+#include 
+#include 
+
+#include 
+// expected-error@-1{{header '' is an implementation detail; #include '' instead}}
+
+#include "include_instead/private2.h"
+// expected-error@-1{{header '"include_instead/private2.h"' is an implementation detail; #include either '' or '"include_instead/public-after.h"' instead}}
+
+#include 
+// expected-error@-1{{header '' is an implementation detail; #include one of {'', '', '"include_instead/public-before.h"'} instead}}
+
+#include 
+#include 
Index: clang/test/Preprocessor/Inputs/include_instead/public-empty.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public-empty.h
@@ -0,0 +1 @@
+// This file simply needs to exist.
Index: clang/test/Preprocessor/Inputs/include_instead/public-before.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public-before.h
@@ -0,0 +1,5 @@
+#pragma GCC system_header
+
+#include  // no warning expected
+#include  // no warning expected
+#include  // no warning expected
Index: clang/test/Preprocessor/Inputs/include_instead/public-after.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public-after.h
@@ -0,0 +1,2 @@
+#include 
+#pragma GCC system_header
Index: clang/test/Preprocessor/Inputs/include_instead/private3.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private3.h
@@ -0,0 +1,5 @@
+#pragma GCC system_header
+
+#pragma clang include_instead()
+#pragma clang include_instead()
+#pragma clang include_instead("include_instead/public-before.h")
Index: clang/test/Preprocessor/Inputs/include_instead/private2.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private2.h
@@ -0,0 +1,4 @@
+#pragma GCC system_header
+
+#pragma clang include_instead()
+#pragma clang include_instead("include_instead/public-after.h")
Index: clang/test/Preprocessor/Inputs/include_instead/private1.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private1.h
@@ -0,0 +1,2 @@
+#pragma GCC system_header
+#pragma clang include_instead()
Index: clang/test/Preprocessor/Inputs/include_instead/private-x.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private-x.h
@@ -0,0 +1,4 @@
+#include 
+
+#pragma GCC system_header
+#pragma clang include_instead()
Index: clang/test/Preprocessor/Inputs/include_instead/non-system-header.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/non-system-heade

[PATCH] D106898: Revert "Revert "[clang][pp] adds '#pragma include_instead'""

2021-07-27 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb updated this revision to Diff 362116.
cjdb retitled this revision from "Revert "Revert "[clang][pp] adds '#pragma 
include_instead'""

Includes regression test for problem noted by @hans." to "Revert "Revert 
"[clang][pp] adds '#pragma include_instead'""".
cjdb edited the summary of this revision.
cjdb added a comment.

updates commit message


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D106898

Files:
  clang/include/clang/Basic/DiagnosticLexKinds.td
  clang/include/clang/Lex/HeaderSearch.h
  clang/include/clang/Lex/Preprocessor.h
  clang/include/clang/Lex/PreprocessorLexer.h
  clang/lib/Lex/Lexer.cpp
  clang/lib/Lex/PPDirectives.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Lex/Pragma.cpp
  clang/test/PCH/ms-pch-macro-include_instead-regression.c
  clang/test/Preprocessor/Inputs/include_instead/bad-syntax.h
  clang/test/Preprocessor/Inputs/include_instead/file-not-found.h
  clang/test/Preprocessor/Inputs/include_instead/non-system-header.h
  clang/test/Preprocessor/Inputs/include_instead/private-x.h
  clang/test/Preprocessor/Inputs/include_instead/private1.h
  clang/test/Preprocessor/Inputs/include_instead/private2.h
  clang/test/Preprocessor/Inputs/include_instead/private3.h
  clang/test/Preprocessor/Inputs/include_instead/public-after.h
  clang/test/Preprocessor/Inputs/include_instead/public-before.h
  clang/test/Preprocessor/Inputs/include_instead/public-empty.h
  clang/test/Preprocessor/include_instead.cpp
  clang/test/Preprocessor/include_instead_file_not_found.cpp

Index: clang/test/Preprocessor/include_instead_file_not_found.cpp
===
--- /dev/null
+++ clang/test/Preprocessor/include_instead_file_not_found.cpp
@@ -0,0 +1,2 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -I %S/Inputs %s
+#include 
Index: clang/test/Preprocessor/include_instead.cpp
===
--- /dev/null
+++ clang/test/Preprocessor/include_instead.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -I %S/Inputs %s
+
+#include 
+#include 
+
+#include 
+// expected-error@-1{{header '' is an implementation detail; #include '' instead}}
+
+#include "include_instead/private2.h"
+// expected-error@-1{{header '"include_instead/private2.h"' is an implementation detail; #include either '' or '"include_instead/public-after.h"' instead}}
+
+#include 
+// expected-error@-1{{header '' is an implementation detail; #include one of {'', '', '"include_instead/public-before.h"'} instead}}
+
+#include 
+#include 
Index: clang/test/Preprocessor/Inputs/include_instead/public-empty.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public-empty.h
@@ -0,0 +1 @@
+// This file simply needs to exist.
Index: clang/test/Preprocessor/Inputs/include_instead/public-before.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public-before.h
@@ -0,0 +1,5 @@
+#pragma GCC system_header
+
+#include  // no warning expected
+#include  // no warning expected
+#include  // no warning expected
Index: clang/test/Preprocessor/Inputs/include_instead/public-after.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public-after.h
@@ -0,0 +1,2 @@
+#include 
+#pragma GCC system_header
Index: clang/test/Preprocessor/Inputs/include_instead/private3.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private3.h
@@ -0,0 +1,5 @@
+#pragma GCC system_header
+
+#pragma clang include_instead()
+#pragma clang include_instead()
+#pragma clang include_instead("include_instead/public-before.h")
Index: clang/test/Preprocessor/Inputs/include_instead/private2.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private2.h
@@ -0,0 +1,4 @@
+#pragma GCC system_header
+
+#pragma clang include_instead()
+#pragma clang include_instead("include_instead/public-after.h")
Index: clang/test/Preprocessor/Inputs/include_instead/private1.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private1.h
@@ -0,0 +1,2 @@
+#pragma GCC system_header
+#pragma clang include_instead()
Index: clang/test/Preprocessor/Inputs/include_instead/private-x.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private-x.h
@@ -0,0 +1,4 @@
+#include 
+
+#pragma GCC system_header
+#pragma clang include_instead()
Index: clang/test/Preprocessor/Inputs/include_instead/non-system-header.h

[PATCH] D106394: [clang][pp] adds '#pragma include_instead'

2021-07-28 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added a comment.

In D106394#2905660 , @dblaikie wrote:

> Just a thought (nothing to hold up this patch/suggest a revert/suggest any 
> immediate action), but:
>
>> The problem with extending this to non-system headers is that you need a way 
>> to tell which headers are allowed to include the detail headers and which 
>> ones are not.
>
> What if the analysis was done on the entire #include path from the current 
> primary source file - rather than from the immediate include location? Then 
> the requirement could be "This header must be directly or indirectly included 
> from one of the headers listed in include_instead, otherwise there will be a 
> warning" - could that generalize to other use cases/not only system headers?

I think this would mean that something like libc++'s `<__ranges/concepts.h>` 
couldn't directly include `<__iterator/concepts.h>`? Also, how does this play 
with `#pragma GCC system_header` detection?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D106394

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


[PATCH] D106898: Revert "Revert "[clang][pp] adds '#pragma include_instead'""

2021-07-28 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb updated this revision to Diff 362479.
cjdb added a comment.

- attempts to get CI passing (@aaron.ballman)
- minimises test case (@hans)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D106898

Files:
  clang/include/clang/Basic/DiagnosticLexKinds.td
  clang/include/clang/Lex/HeaderSearch.h
  clang/include/clang/Lex/Preprocessor.h
  clang/include/clang/Lex/PreprocessorLexer.h
  clang/lib/Lex/Lexer.cpp
  clang/lib/Lex/PPDirectives.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Lex/Pragma.cpp
  clang/test/PCH/ms-pch-macro-include_instead-regression.c
  clang/test/Preprocessor/Inputs/include_instead/bad-syntax.h
  clang/test/Preprocessor/Inputs/include_instead/file-not-found.h
  clang/test/Preprocessor/Inputs/include_instead/non-system-header.h
  clang/test/Preprocessor/Inputs/include_instead/private-x.h
  clang/test/Preprocessor/Inputs/include_instead/private1.h
  clang/test/Preprocessor/Inputs/include_instead/private2.h
  clang/test/Preprocessor/Inputs/include_instead/private3.h
  clang/test/Preprocessor/Inputs/include_instead/public-after.h
  clang/test/Preprocessor/Inputs/include_instead/public-before.h
  clang/test/Preprocessor/Inputs/include_instead/public-empty.h
  clang/test/Preprocessor/include_instead.cpp
  clang/test/Preprocessor/include_instead_file_not_found.cpp

Index: clang/test/Preprocessor/include_instead_file_not_found.cpp
===
--- /dev/null
+++ clang/test/Preprocessor/include_instead_file_not_found.cpp
@@ -0,0 +1,2 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -I %S/Inputs %s
+#include 
Index: clang/test/Preprocessor/include_instead.cpp
===
--- /dev/null
+++ clang/test/Preprocessor/include_instead.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -I %S/Inputs %s
+
+#include 
+#include 
+
+#include 
+// expected-error@-1{{header '' is an implementation detail; #include '' instead}}
+
+#include "include_instead/private2.h"
+// expected-error@-1{{header '"include_instead/private2.h"' is an implementation detail; #include either '' or '"include_instead/public-after.h"' instead}}
+
+#include 
+// expected-error@-1{{header '' is an implementation detail; #include one of {'', '', '"include_instead/public-before.h"'} instead}}
+
+#include 
+#include 
Index: clang/test/Preprocessor/Inputs/include_instead/public-empty.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public-empty.h
@@ -0,0 +1 @@
+// This file simply needs to exist.
Index: clang/test/Preprocessor/Inputs/include_instead/public-before.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public-before.h
@@ -0,0 +1,5 @@
+#pragma GCC system_header
+
+#include  // no warning expected
+#include  // no warning expected
+#include  // no warning expected
Index: clang/test/Preprocessor/Inputs/include_instead/public-after.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public-after.h
@@ -0,0 +1,2 @@
+#include 
+#pragma GCC system_header
Index: clang/test/Preprocessor/Inputs/include_instead/private3.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private3.h
@@ -0,0 +1,5 @@
+#pragma GCC system_header
+
+#pragma clang include_instead()
+#pragma clang include_instead()
+#pragma clang include_instead("include_instead/public-before.h")
Index: clang/test/Preprocessor/Inputs/include_instead/private2.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private2.h
@@ -0,0 +1,4 @@
+#pragma GCC system_header
+
+#pragma clang include_instead()
+#pragma clang include_instead("include_instead/public-after.h")
Index: clang/test/Preprocessor/Inputs/include_instead/private1.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private1.h
@@ -0,0 +1,2 @@
+#pragma GCC system_header
+#pragma clang include_instead()
Index: clang/test/Preprocessor/Inputs/include_instead/private-x.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private-x.h
@@ -0,0 +1,4 @@
+#include 
+
+#pragma GCC system_header
+#pragma clang include_instead()
Index: clang/test/Preprocessor/Inputs/include_instead/non-system-header.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/non-system-header.h
@@ -0,0 +1,2 @@
+#pragma clang include_instead()
+// expected-error@-1{{'#pragma clang include_instead' cannot be u

[PATCH] D106898: Revert "Revert "[clang][pp] adds '#pragma include_instead'""

2021-07-29 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb updated this revision to Diff 362806.
cjdb marked an inline comment as done.
cjdb added a subscriber: tstellar.
cjdb added a comment.

fixes up formatting and testing

Will merge post-CI. @aaron.ballman do you approve this to be cherry-picked into 
LLVM 13? (cc @tstellar)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D106898

Files:
  clang/include/clang/Basic/DiagnosticLexKinds.td
  clang/include/clang/Lex/HeaderSearch.h
  clang/include/clang/Lex/Preprocessor.h
  clang/include/clang/Lex/PreprocessorLexer.h
  clang/lib/Lex/Lexer.cpp
  clang/lib/Lex/PPDirectives.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Lex/Pragma.cpp
  clang/test/PCH/ms-pch-macro-include_instead-regression.c
  clang/test/Preprocessor/Inputs/include_instead/bad-syntax.h
  clang/test/Preprocessor/Inputs/include_instead/file-not-found.h
  clang/test/Preprocessor/Inputs/include_instead/non-system-header.h
  clang/test/Preprocessor/Inputs/include_instead/private-x.h
  clang/test/Preprocessor/Inputs/include_instead/private1.h
  clang/test/Preprocessor/Inputs/include_instead/private2.h
  clang/test/Preprocessor/Inputs/include_instead/private3.h
  clang/test/Preprocessor/Inputs/include_instead/public-after.h
  clang/test/Preprocessor/Inputs/include_instead/public-before.h
  clang/test/Preprocessor/Inputs/include_instead/public-empty.h
  clang/test/Preprocessor/include_instead.cpp
  clang/test/Preprocessor/include_instead_file_not_found.cpp

Index: clang/test/Preprocessor/include_instead_file_not_found.cpp
===
--- /dev/null
+++ clang/test/Preprocessor/include_instead_file_not_found.cpp
@@ -0,0 +1,2 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -I %S/Inputs %s
+#include 
Index: clang/test/Preprocessor/include_instead.cpp
===
--- /dev/null
+++ clang/test/Preprocessor/include_instead.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -I %S/Inputs %s
+
+#include 
+#include 
+
+#include 
+// expected-error@-1{{header '' is an implementation detail; #include '' instead}}
+
+#include "include_instead/private2.h"
+// expected-error@-1{{header '"include_instead/private2.h"' is an implementation detail; #include either '' or '"include_instead/public-after.h"' instead}}
+
+#include 
+// expected-error@-1{{header '' is an implementation detail; #include one of {'', '', '"include_instead/public-before.h"'} instead}}
+
+#include 
+#include 
Index: clang/test/Preprocessor/Inputs/include_instead/public-empty.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public-empty.h
@@ -0,0 +1 @@
+// This file simply needs to exist.
Index: clang/test/Preprocessor/Inputs/include_instead/public-before.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public-before.h
@@ -0,0 +1,5 @@
+#pragma GCC system_header
+
+#include  // no warning expected
+#include  // no warning expected
+#include  // no warning expected
Index: clang/test/Preprocessor/Inputs/include_instead/public-after.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public-after.h
@@ -0,0 +1,2 @@
+#include 
+#pragma GCC system_header
Index: clang/test/Preprocessor/Inputs/include_instead/private3.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private3.h
@@ -0,0 +1,5 @@
+#pragma GCC system_header
+
+#pragma clang include_instead()
+#pragma clang include_instead()
+#pragma clang include_instead("include_instead/public-before.h")
Index: clang/test/Preprocessor/Inputs/include_instead/private2.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private2.h
@@ -0,0 +1,4 @@
+#pragma GCC system_header
+
+#pragma clang include_instead()
+#pragma clang include_instead("include_instead/public-after.h")
Index: clang/test/Preprocessor/Inputs/include_instead/private1.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private1.h
@@ -0,0 +1,2 @@
+#pragma GCC system_header
+#pragma clang include_instead()
Index: clang/test/Preprocessor/Inputs/include_instead/private-x.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private-x.h
@@ -0,0 +1,4 @@
+#include 
+
+#pragma GCC system_header
+#pragma clang include_instead()
Index: clang/test/Preprocessor/Inputs/include_instead/non-system-header.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead

[PATCH] D106898: Revert "Revert "[clang][pp] adds '#pragma include_instead'""

2021-07-29 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added inline comments.



Comment at: clang/include/clang/Basic/DiagnosticLexKinds.td:307
+def err_pragma_include_instead_system_reserved : Error<
+  "header '%0' is an implementation detail; #include %select{'%2'|either '%2' 
or '%3'|one of %2}1 instead">;
+

aaron.ballman wrote:
> 80-col wrapping.
Surprised this made it past the first time.



Comment at: clang/test/PCH/ms-pch-macro-include_instead-regression.c:2
+// Enabling MS extensions should allow us to add BAR definitions.
+// RUN: %clang_cc1 -DMSEXT -fms-extensions -DBAZ=\"Inputs/pch-through1.h\" 
-emit-pch -o %t1.pch
+// RUN: %clang_cc1 -DMSEXT -fms-extensions -include-pch %t1.pch -verify %s

aaron.ballman wrote:
> This fixes the shell issue when I try it out locally on Windows.
Thanks!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D106898

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


[PATCH] D106898: Revert "Revert "[clang][pp] adds '#pragma include_instead'""

2021-07-29 Thread Christopher Di Bella via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG087195419719: Revert "Revert "[clang][pp] adds 
'#pragma include_instead'"" (authored by cjdb).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D106898

Files:
  clang/include/clang/Basic/DiagnosticLexKinds.td
  clang/include/clang/Lex/HeaderSearch.h
  clang/include/clang/Lex/Preprocessor.h
  clang/include/clang/Lex/PreprocessorLexer.h
  clang/lib/Lex/Lexer.cpp
  clang/lib/Lex/PPDirectives.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Lex/Pragma.cpp
  clang/test/PCH/ms-pch-macro-include_instead-regression.c
  clang/test/Preprocessor/Inputs/include_instead/bad-syntax.h
  clang/test/Preprocessor/Inputs/include_instead/file-not-found.h
  clang/test/Preprocessor/Inputs/include_instead/non-system-header.h
  clang/test/Preprocessor/Inputs/include_instead/private-x.h
  clang/test/Preprocessor/Inputs/include_instead/private1.h
  clang/test/Preprocessor/Inputs/include_instead/private2.h
  clang/test/Preprocessor/Inputs/include_instead/private3.h
  clang/test/Preprocessor/Inputs/include_instead/public-after.h
  clang/test/Preprocessor/Inputs/include_instead/public-before.h
  clang/test/Preprocessor/Inputs/include_instead/public-empty.h
  clang/test/Preprocessor/include_instead.cpp
  clang/test/Preprocessor/include_instead_file_not_found.cpp

Index: clang/test/Preprocessor/include_instead_file_not_found.cpp
===
--- /dev/null
+++ clang/test/Preprocessor/include_instead_file_not_found.cpp
@@ -0,0 +1,2 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -I %S/Inputs %s
+#include 
Index: clang/test/Preprocessor/include_instead.cpp
===
--- /dev/null
+++ clang/test/Preprocessor/include_instead.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -I %S/Inputs %s
+
+#include 
+#include 
+
+#include 
+// expected-error@-1{{header '' is an implementation detail; #include '' instead}}
+
+#include "include_instead/private2.h"
+// expected-error@-1{{header '"include_instead/private2.h"' is an implementation detail; #include either '' or '"include_instead/public-after.h"' instead}}
+
+#include 
+// expected-error@-1{{header '' is an implementation detail; #include one of {'', '', '"include_instead/public-before.h"'} instead}}
+
+#include 
+#include 
Index: clang/test/Preprocessor/Inputs/include_instead/public-empty.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public-empty.h
@@ -0,0 +1 @@
+// This file simply needs to exist.
Index: clang/test/Preprocessor/Inputs/include_instead/public-before.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public-before.h
@@ -0,0 +1,5 @@
+#pragma GCC system_header
+
+#include  // no warning expected
+#include  // no warning expected
+#include  // no warning expected
Index: clang/test/Preprocessor/Inputs/include_instead/public-after.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/public-after.h
@@ -0,0 +1,2 @@
+#include 
+#pragma GCC system_header
Index: clang/test/Preprocessor/Inputs/include_instead/private3.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private3.h
@@ -0,0 +1,5 @@
+#pragma GCC system_header
+
+#pragma clang include_instead()
+#pragma clang include_instead()
+#pragma clang include_instead("include_instead/public-before.h")
Index: clang/test/Preprocessor/Inputs/include_instead/private2.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private2.h
@@ -0,0 +1,4 @@
+#pragma GCC system_header
+
+#pragma clang include_instead()
+#pragma clang include_instead("include_instead/public-after.h")
Index: clang/test/Preprocessor/Inputs/include_instead/private1.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private1.h
@@ -0,0 +1,2 @@
+#pragma GCC system_header
+#pragma clang include_instead()
Index: clang/test/Preprocessor/Inputs/include_instead/private-x.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/private-x.h
@@ -0,0 +1,4 @@
+#include 
+
+#pragma GCC system_header
+#pragma clang include_instead()
Index: clang/test/Preprocessor/Inputs/include_instead/non-system-header.h
===
--- /dev/null
+++ clang/test/Preprocessor/Inputs/include_instead/non-system-header.h
@@ -0,0 +1,2 @@
+#pragma clang include_instead()
+// expected-error@-

[PATCH] D116203: [clang] adds unary type transformations as compiler built-ins

2022-04-06 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added a comment.

In D116203#3431612 , @rjmccall wrote:

> In D116203#3430332 , @aaron.ballman 
> wrote:
>
>> In D116203#3425512 , @cjdb wrote:
>>
>>> I've noticed that libstdc++ has `using __remove_cv = typename 
>>> remove_cv::type`, which causes Clang to chuck a wobbly. Changing from 
>>> `KEYWORD` to `TYPE_TRAIT_1` didn't seem to fix anything.
>>> Is there a way we can work around this, or should we just rename 
>>> `__remove_cv` and friends to something else?
>>
>> You could work around it by taking note that you're in a libstdc++ system 
>> header and do a special dance, but because these are in the implementation's 
>> namespace, I think it's probably kinder for everyone to just pick a 
>> different name.

I was hoping we could do something similar to `struct __remove_cv` which would 
issue a warning?

>> If you wanted to be especially mean, you could go with `__remove_cvr`, but 
>> I'd suggest `__remove_cv_qualifiers` instead. However, what about `restrict` 
>> qualifiers? We support them in C++: https://godbolt.org/z/11EPefhjf
>
> Along with a fair number of other vendor qualifiers, yeah.  I think you have 
> to make a policy decision about whether the intent of `std::remove_cv` is 
> really to just remove CV qualifiers or to produce an unqualified type (at the 
> outermost level).  The former is probably more defensible, even if it makes 
> the transform less useful in the presence of extended qualifiers.

I'm partial to `std::remove_cv` being faithful to its name, unless existing 
implementations do something else already. I don't mind adding support for the 
other stuff, but if there's more than just add/remove `restrict`, we're going 
to have a combinatorial explosion for removes. Is there an alternate way we can 
approach this?
Possibly:

  template
  using remove_const_t = __remove_qualifiers(T, const);
  
  
  template
  using remove_reference_t = __remove_qualifiers(T, &, &&);
  
  template
  using remove_rcvref_t = __remove_qualifiers(T, const, volatile, restrict, &, 
&&); // rcv instead of cvr to prevent a typo with remove_cvref_t


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D116203

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


[PATCH] D116203: [clang] adds unary type transformations as compiler built-ins

2022-04-07 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added a comment.

In D116203#3435729 , @aaron.ballman 
wrote:

> In D116203#3434761 , @rjmccall 
> wrote:
>
>> In D116203#3434515 , @cjdb wrote:
>>
>>> In D116203#3431612 , @rjmccall 
>>> wrote:
>>>
 In D116203#3430332 , 
 @aaron.ballman wrote:

> In D116203#3425512 , @cjdb 
> wrote:
>
>> I've noticed that libstdc++ has `using __remove_cv = typename 
>> remove_cv::type`, which causes Clang to chuck a wobbly. Changing from 
>> `KEYWORD` to `TYPE_TRAIT_1` didn't seem to fix anything.
>> Is there a way we can work around this, or should we just rename 
>> `__remove_cv` and friends to something else?
>
> You could work around it by taking note that you're in a libstdc++ system 
> header and do a special dance, but because these are in the 
> implementation's namespace, I think it's probably kinder for everyone to 
> just pick a different name.
>>>
>>> I was hoping we could do something similar to `struct __remove_cv` which 
>>> would issue a warning?
>>>
> If you wanted to be especially mean, you could go with `__remove_cvr`, 
> but I'd suggest `__remove_cv_qualifiers` instead. However, what about 
> `restrict` qualifiers? We support them in C++: 
> https://godbolt.org/z/11EPefhjf

 Along with a fair number of other vendor qualifiers, yeah.  I think you 
 have to make a policy decision about whether the intent of 
 `std::remove_cv` is really to just remove CV qualifiers or to produce an 
 unqualified type (at the outermost level).  The former is probably more 
 defensible, even if it makes the transform less useful in the presence of 
 extended qualifiers.
>>>
>>> I'm partial to `std::remove_cv` being faithful to its name, unless existing 
>>> implementations do something else already. I don't mind adding support for 
>>> the other stuff, but if there's more than just add/remove `restrict`, we're 
>>> going to have a combinatorial explosion for removes. Is there an alternate 
>>> way we can approach this?
>>> Possibly:
>>>
>>>   template
>>>   using remove_const_t = __remove_qualifiers(T, const);
>>>   
>>>   
>>>   template
>>>   using remove_reference_t = __remove_qualifiers(T, &, &&);
>>>   
>>>   template
>>>   using remove_rcvref_t = __remove_qualifiers(T, const, volatile, restrict, 
>>> &, &&); // rcv instead of cvr to prevent a typo with remove_cvref_t
>>
>> I don't think it's worth adding that parsing complexity for a builtin that 
>> we expect to only be used in system headers.  Let's just remove `const` and 
>> `volatile` and leave other qualifiers in place.
>
> I come down on the opposite side of the fence and think it should remove all 
> qualifiers (or that should be an interface we support in addition to removing 
> just cv qualifiers). WG14 adopted 
> https://www9.open-std.org/jtc1/sc22/wg14/www/docs/n2927.htm into C23 with a 
> `remove_quals` function which removes *all* qualifiers (including `_Atomic`), 
> as an example. But even in C++ mode, I fail to see why we wouldn't want 
>  interface for stripping `__restrict` the same as `const` or `volatile` 
> along with some interface for stripping all qualifiers period (I don't see a 
> huge need for a `__remove_cvr` if we have the ability to remove all 
> qualifiers, so I don't think we need the combinatorial explosion or a complex 
> interface). Basically -- if we have extensions like `__restrict` or _Atomic, 
> we should fully support them rather than halfway do it.

Having `__remove_cv` do more than it's advertised to do doesn't sound like a 
great idea to me. Both libc++ 

 and libstdc++ 

 define `std::remove_cv` without extensions, and I think it would be surprising 
for `__remove_cv` to remove anything else.

I'm not against adding `__remove_restrict`, `__remove_qualifiers` (although 
"qualifier" could imply ref-qualifiers too?), etc.. I suppose that in the rare 
case someone wants to remove `volatile restrict` and keep `const&`, it's 
possible to do `__add_const(__remove_qualifiers(T)&)`.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D116203

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


[PATCH] D116280: [clang] adds unary type trait checks as compiler built-ins

2022-04-10 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb updated this revision to Diff 421836.
cjdb edited the summary of this revision.
cjdb added a comment.
Herald added a project: All.

adds `__is_copy_constructible`, `__is_copy_assignable`, 
`__is_move_constructible` (WIP), and `__is_move_assignable` (incomplete)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D116280

Files:
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/lib/Sema/SemaType.cpp
  clang/test/SemaCXX/type-traits.cpp

Index: clang/test/SemaCXX/type-traits.cpp
===
--- clang/test/SemaCXX/type-traits.cpp
+++ clang/test/SemaCXX/type-traits.cpp
@@ -345,11 +345,19 @@
 }
 
 typedef Enum EnumType;
+typedef EnumClass EnumClassType;
 
 void is_enum()
 {
   { int arr[T(__is_enum(Enum))]; }
   { int arr[T(__is_enum(EnumType))]; }
+  { int arr[T(__is_enum(SignedEnum))]; }
+  { int arr[T(__is_enum(UnsignedEnum))]; }
+
+  { int arr[T(__is_enum(EnumClass))]; }
+  { int arr[T(__is_enum(EnumClassType))]; }
+  { int arr[T(__is_enum(SignedEnumClass))]; }
+  { int arr[T(__is_enum(UnsignedEnumClass))]; }
 
   { int arr[F(__is_enum(int))]; }
   { int arr[F(__is_enum(Union))]; }
@@ -363,6 +371,30 @@
   { int arr[F(__is_enum(HasAnonymousUnion))]; }
 }
 
+void is_scoped_enum()
+{
+  { int arr[F(__is_scoped_enum(Enum))]; }
+  { int arr[F(__is_scoped_enum(EnumType))]; }
+  { int arr[F(__is_scoped_enum(SignedEnum))]; }
+  { int arr[F(__is_scoped_enum(UnsignedEnum))]; }
+
+  { int arr[T(__is_scoped_enum(EnumClass))]; }
+  { int arr[T(__is_scoped_enum(EnumClassType))]; }
+  { int arr[T(__is_scoped_enum(SignedEnumClass))]; }
+  { int arr[T(__is_scoped_enum(UnsignedEnumClass))]; }
+
+  { int arr[F(__is_scoped_enum(int))]; }
+  { int arr[F(__is_scoped_enum(Union))]; }
+  { int arr[F(__is_scoped_enum(Int))]; }
+  { int arr[F(__is_scoped_enum(IntAr))]; }
+  { int arr[F(__is_scoped_enum(UnionAr))]; }
+  { int arr[F(__is_scoped_enum(Derives))]; }
+  { int arr[F(__is_scoped_enum(ClassType))]; }
+  { int arr[F(__is_scoped_enum(cvoid))]; }
+  { int arr[F(__is_scoped_enum(IntArNB))]; }
+  { int arr[F(__is_scoped_enum(HasAnonymousUnion))]; }
+}
+
 struct FinalClass final {
 };
 
@@ -702,6 +734,66 @@
   int t31[F(__is_array(cvoid*))];
 }
 
+void is_bounded_array()
+{
+  int t01[T(__is_bounded_array(IntAr))];
+  int t02[F(__is_bounded_array(IntArNB))];
+  int t03[T(__is_bounded_array(UnionAr))];
+
+  int t10[F(__is_bounded_array(void))];
+  int t11[F(__is_bounded_array(cvoid))];
+  int t12[F(__is_bounded_array(float))];
+  int t13[F(__is_bounded_array(double))];
+  int t14[F(__is_bounded_array(long double))];
+  int t15[F(__is_bounded_array(bool))];
+  int t16[F(__is_bounded_array(char))];
+  int t17[F(__is_bounded_array(signed char))];
+  int t18[F(__is_bounded_array(unsigned char))];
+  int t19[F(__is_bounded_array(wchar_t))];
+  int t20[F(__is_bounded_array(short))];
+  int t21[F(__is_bounded_array(unsigned short))];
+  int t22[F(__is_bounded_array(int))];
+  int t23[F(__is_bounded_array(unsigned int))];
+  int t24[F(__is_bounded_array(long))];
+  int t25[F(__is_bounded_array(unsigned long))];
+  int t26[F(__is_bounded_array(Union))];
+  int t27[F(__is_bounded_array(Derives))];
+  int t28[F(__is_bounded_array(ClassType))];
+  int t29[F(__is_bounded_array(Enum))];
+  int t30[F(__is_bounded_array(void*))];
+  int t31[F(__is_bounded_array(cvoid*))];
+}
+
+void is_unbounded_array()
+{
+  int t01[F(__is_unbounded_array(IntAr))];
+  int t02[T(__is_unbounded_array(IntArNB))];
+  int t03[F(__is_unbounded_array(UnionAr))];
+
+  int t10[F(__is_unbounded_array(void))];
+  int t11[F(__is_unbounded_array(cvoid))];
+  int t12[F(__is_unbounded_array(float))];
+  int t13[F(__is_unbounded_array(double))];
+  int t14[F(__is_unbounded_array(long double))];
+  int t15[F(__is_unbounded_array(bool))];
+  int t16[F(__is_unbounded_array(char))];
+  int t17[F(__is_unbounded_array(signed char))];
+  int t18[F(__is_unbounded_array(unsigned char))];
+  int t19[F(__is_unbounded_array(wchar_t))];
+  int t20[F(__is_unbounded_array(short))];
+  int t21[F(__is_unbounded_array(unsigned short))];
+  int t22[F(__is_unbounded_array(int))];
+  int t23[F(__is_unbounded_array(unsigned int))];
+  int t24[F(__is_unbounded_array(long))];
+  int t25[F(__is_unbounded_array(unsigned long))];
+  int t26[F(__is_unbounded_array(Union))];
+  int t27[F(__is_unbounded_array(Derives))];
+  int t28[F(__is_unbounded_array(ClassType))];
+  int t29[F(__is_unbounded_array(Enum))];
+  int t30[F(__is_unbounded_array(void*))];
+  int t31[F(__is_unbounded_array(cvoid*))];
+}
+
 template  void tmpl_func(T&) {}
 
 template  struct type_wrapper {
@@ -934,6 +1026,43 @@
   int t34[F(__is_pointer(void (StructWithMembers::*) ()))];
 }
 
+void is_null_pointer()
+{
+  StructWithMembers x;
+
+  int t00[T(__is_nullptr(dec

[PATCH] D123885: Revert "Revert "Revert "[clang][pp] adds '#pragma include_instead'"""

2022-04-15 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb created this revision.
cjdb added reviewers: rsmith, aaron.ballman.
Herald added subscribers: dexonsmith, usaxena95, kadircet, arphaman.
Herald added a project: All.
cjdb requested review of this revision.
Herald added projects: clang, clang-tools-extra.
Herald added a subscriber: cfe-commits.

> Includes regression test for problem noted by @hans.
> is reverts commit 973de71 
> .
>
> Differential Revision: https://reviews.llvm.org/D106898

Feature implemented as-is is fairly expensive and hasn't been used by
libc++. A potential reimplementation is possible if libc++ become
interested in this feature again.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D123885

Files:
  clang-tools-extra/clangd/Selection.cpp
  clang-tools-extra/pseudo/lib/Lex.cpp
  clang/include/clang/Basic/DiagnosticLexKinds.td
  clang/include/clang/Basic/SourceManager.h
  clang/include/clang/Lex/HeaderSearch.h
  clang/include/clang/Lex/Lexer.h
  clang/include/clang/Lex/Preprocessor.h
  clang/include/clang/Lex/PreprocessorLexer.h
  clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
  clang/lib/Lex/Lexer.cpp
  clang/lib/Lex/PPDirectives.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Lex/Pragma.cpp
  clang/test/PCH/ms-pch-macro-include_instead-regression.c
  clang/test/Preprocessor/Inputs/include_instead/bad-syntax.h
  clang/test/Preprocessor/Inputs/include_instead/file-not-found.h
  clang/test/Preprocessor/Inputs/include_instead/non-system-header.h
  clang/test/Preprocessor/Inputs/include_instead/private-x.h
  clang/test/Preprocessor/Inputs/include_instead/private1.h
  clang/test/Preprocessor/Inputs/include_instead/private2.h
  clang/test/Preprocessor/Inputs/include_instead/private3.h
  clang/test/Preprocessor/Inputs/include_instead/public-after.h
  clang/test/Preprocessor/Inputs/include_instead/public-before.h
  clang/test/Preprocessor/Inputs/include_instead/public-empty.h
  clang/test/Preprocessor/include_instead.cpp
  clang/test/Preprocessor/include_instead_file_not_found.cpp

Index: clang/test/Preprocessor/include_instead_file_not_found.cpp
===
--- clang/test/Preprocessor/include_instead_file_not_found.cpp
+++ /dev/null
@@ -1,2 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -I %S/Inputs %s
-#include 
Index: clang/test/Preprocessor/include_instead.cpp
===
--- clang/test/Preprocessor/include_instead.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -I %S/Inputs %s
-
-#include 
-#include 
-
-#include 
-// expected-error@-1{{header '' is an implementation detail; #include '' instead}}
-
-#include "include_instead/private2.h"
-// expected-error@-1{{header '"include_instead/private2.h"' is an implementation detail; #include either '' or '"include_instead/public-after.h"' instead}}
-
-#include 
-// expected-error@-1{{header '' is an implementation detail; #include one of {'', '', '"include_instead/public-before.h"'} instead}}
-
-#include 
-#include 
Index: clang/test/Preprocessor/Inputs/include_instead/public-empty.h
===
--- clang/test/Preprocessor/Inputs/include_instead/public-empty.h
+++ /dev/null
@@ -1 +0,0 @@
-// This file simply needs to exist.
Index: clang/test/Preprocessor/Inputs/include_instead/public-before.h
===
--- clang/test/Preprocessor/Inputs/include_instead/public-before.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#pragma GCC system_header
-
-#include  // no warning expected
-#include  // no warning expected
-#include  // no warning expected
Index: clang/test/Preprocessor/Inputs/include_instead/public-after.h
===
--- clang/test/Preprocessor/Inputs/include_instead/public-after.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#include 
-#pragma GCC system_header
Index: clang/test/Preprocessor/Inputs/include_instead/private3.h
===
--- clang/test/Preprocessor/Inputs/include_instead/private3.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#pragma GCC system_header
-
-#pragma clang include_instead()
-#pragma clang include_instead()
-#pragma clang include_instead("include_instead/public-before.h")
Index: clang/test/Preprocessor/Inputs/include_instead/private2.h
===
--- clang/test/Preprocessor/Inputs/include_instead/private2.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#pragma GCC system_header
-
-#pragma clang include_instead()
-#pragma clang include_instead("include_instead/public-after.h")
Index: clang/test/Preprocessor/Inputs/include_instead/private1.h
===
--- clang/test/Preprocessor/Inputs/include_instead/private1.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#pragma GCC 

[PATCH] D116203: [clang] adds unary type transformations as compiler built-ins

2022-04-16 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb marked an inline comment as done.
cjdb added inline comments.



Comment at: clang/lib/Sema/SemaType.cpp:9113
+  BaseType.isReferenceable() || BaseType->isVoidType()
+  ? BuildPointerType(BaseType.getNonReferenceType(), Loc, EntityName)
+  : BaseType;

cjdb wrote:
> erichkeane wrote:
> > Do we at any point want this builtin to be address-space aware?  
> I'm not against this functionality, but there isn't (currently) motivation 
> for it. WDYT about `__add_pointer(T, address_space)`? Do we want this to be a 
> separate builtin (e.g. `__add_pointer_with_address_space(T, address_space)`)?
I don't think handling address spaces is worth the trouble: we can always do 
`__add_pointer(int __attribute__((address_space(1` if desired (I added two 
tests to confirm this). I did need to fix `__remove_pointer` so that it also 
removes address spaces, so thank you for flagging this :)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D116203

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


[PATCH] D116280: [clang] adds unary type trait checks as compiler built-ins

2022-04-16 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb updated this revision to Diff 423280.
cjdb marked 3 inline comments as done.
cjdb added a comment.

- finishes `__is_move_constructible` and `__is_move_assignable`
- fixes detecting C++ mode
- clang-formats


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D116280

Files:
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/lib/Sema/SemaType.cpp
  clang/test/SemaCXX/type-traits.cpp

Index: clang/test/SemaCXX/type-traits.cpp
===
--- clang/test/SemaCXX/type-traits.cpp
+++ clang/test/SemaCXX/type-traits.cpp
@@ -345,11 +345,19 @@
 }
 
 typedef Enum EnumType;
+typedef EnumClass EnumClassType;
 
 void is_enum()
 {
   { int arr[T(__is_enum(Enum))]; }
   { int arr[T(__is_enum(EnumType))]; }
+  { int arr[T(__is_enum(SignedEnum))]; }
+  { int arr[T(__is_enum(UnsignedEnum))]; }
+
+  { int arr[T(__is_enum(EnumClass))]; }
+  { int arr[T(__is_enum(EnumClassType))]; }
+  { int arr[T(__is_enum(SignedEnumClass))]; }
+  { int arr[T(__is_enum(UnsignedEnumClass))]; }
 
   { int arr[F(__is_enum(int))]; }
   { int arr[F(__is_enum(Union))]; }
@@ -363,6 +371,29 @@
   { int arr[F(__is_enum(HasAnonymousUnion))]; }
 }
 
+void is_scoped_enum() {
+  { int arr[F(__is_scoped_enum(Enum))]; }
+  { int arr[F(__is_scoped_enum(EnumType))]; }
+  { int arr[F(__is_scoped_enum(SignedEnum))]; }
+  { int arr[F(__is_scoped_enum(UnsignedEnum))]; }
+
+  { int arr[T(__is_scoped_enum(EnumClass))]; }
+  { int arr[T(__is_scoped_enum(EnumClassType))]; }
+  { int arr[T(__is_scoped_enum(SignedEnumClass))]; }
+  { int arr[T(__is_scoped_enum(UnsignedEnumClass))]; }
+
+  { int arr[F(__is_scoped_enum(int))]; }
+  { int arr[F(__is_scoped_enum(Union))]; }
+  { int arr[F(__is_scoped_enum(Int))]; }
+  { int arr[F(__is_scoped_enum(IntAr))]; }
+  { int arr[F(__is_scoped_enum(UnionAr))]; }
+  { int arr[F(__is_scoped_enum(Derives))]; }
+  { int arr[F(__is_scoped_enum(ClassType))]; }
+  { int arr[F(__is_scoped_enum(cvoid))]; }
+  { int arr[F(__is_scoped_enum(IntArNB))]; }
+  { int arr[F(__is_scoped_enum(HasAnonymousUnion))]; }
+}
+
 struct FinalClass final {
 };
 
@@ -702,6 +733,64 @@
   int t31[F(__is_array(cvoid*))];
 }
 
+void is_bounded_array() {
+  int t01[T(__is_bounded_array(IntAr))];
+  int t02[F(__is_bounded_array(IntArNB))];
+  int t03[T(__is_bounded_array(UnionAr))];
+
+  int t10[F(__is_bounded_array(void))];
+  int t11[F(__is_bounded_array(cvoid))];
+  int t12[F(__is_bounded_array(float))];
+  int t13[F(__is_bounded_array(double))];
+  int t14[F(__is_bounded_array(long double))];
+  int t15[F(__is_bounded_array(bool))];
+  int t16[F(__is_bounded_array(char))];
+  int t17[F(__is_bounded_array(signed char))];
+  int t18[F(__is_bounded_array(unsigned char))];
+  int t19[F(__is_bounded_array(wchar_t))];
+  int t20[F(__is_bounded_array(short))];
+  int t21[F(__is_bounded_array(unsigned short))];
+  int t22[F(__is_bounded_array(int))];
+  int t23[F(__is_bounded_array(unsigned int))];
+  int t24[F(__is_bounded_array(long))];
+  int t25[F(__is_bounded_array(unsigned long))];
+  int t26[F(__is_bounded_array(Union))];
+  int t27[F(__is_bounded_array(Derives))];
+  int t28[F(__is_bounded_array(ClassType))];
+  int t29[F(__is_bounded_array(Enum))];
+  int t30[F(__is_bounded_array(void *))];
+  int t31[F(__is_bounded_array(cvoid *))];
+}
+
+void is_unbounded_array() {
+  int t01[F(__is_unbounded_array(IntAr))];
+  int t02[T(__is_unbounded_array(IntArNB))];
+  int t03[F(__is_unbounded_array(UnionAr))];
+
+  int t10[F(__is_unbounded_array(void))];
+  int t11[F(__is_unbounded_array(cvoid))];
+  int t12[F(__is_unbounded_array(float))];
+  int t13[F(__is_unbounded_array(double))];
+  int t14[F(__is_unbounded_array(long double))];
+  int t15[F(__is_unbounded_array(bool))];
+  int t16[F(__is_unbounded_array(char))];
+  int t17[F(__is_unbounded_array(signed char))];
+  int t18[F(__is_unbounded_array(unsigned char))];
+  int t19[F(__is_unbounded_array(wchar_t))];
+  int t20[F(__is_unbounded_array(short))];
+  int t21[F(__is_unbounded_array(unsigned short))];
+  int t22[F(__is_unbounded_array(int))];
+  int t23[F(__is_unbounded_array(unsigned int))];
+  int t24[F(__is_unbounded_array(long))];
+  int t25[F(__is_unbounded_array(unsigned long))];
+  int t26[F(__is_unbounded_array(Union))];
+  int t27[F(__is_unbounded_array(Derives))];
+  int t28[F(__is_unbounded_array(ClassType))];
+  int t29[F(__is_unbounded_array(Enum))];
+  int t30[F(__is_unbounded_array(void *))];
+  int t31[F(__is_unbounded_array(cvoid *))];
+}
+
 template  void tmpl_func(T&) {}
 
 template  struct type_wrapper {
@@ -934,6 +1023,42 @@
   int t34[F(__is_pointer(void (StructWithMembers::*) ()))];
 }
 
+void is_null_pointer() {
+  StructWithMembers x;
+
+  int t00[T(__is_nullptr(decltype(nullptr)))];
+  int t01[F(__is_nullptr(void *))];

[PATCH] D116280: [clang] adds unary type trait checks as compiler built-ins

2022-04-16 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added inline comments.



Comment at: clang/lib/Sema/SemaExprCXX.cpp:4889-4890
 return T->isArrayType();
+  case UTT_IsBoundedArray:
+return T->isArrayType() && !T->isIncompleteArrayType();
+  case UTT_IsUnboundedArray:

aaron.ballman wrote:
> Is a VLA a bounded array? (We support those as an extension in C++, 
> unfortunately.)
`__is_bounded_array(T)` is true when "`T` is an array type of known bound". Do 
VLAs meet this criteria?



Comment at: clang/lib/Sema/SemaExprCXX.cpp:5289
+if (UTT == UTT_IsCopyAssignable) {
+  return EvaluateBinaryTypeTrait(Self, BTT_IsAssignable, 
Self.BuildReferenceType(T, true, KeyLoc, T.getBaseTypeIdentifier()), 
AssigneeType, KeyLoc);
+}

aaron.ballman wrote:
> It looks like this file could stand to be clang formatted.
Yeah, there was a time where `arc diff` did the formatting automatically, but 
it seems that day has passed :(



Comment at: clang/test/SemaCXX/type-traits.cpp:764
+  int t30[F(__is_bounded_array(void*))];
+  int t31[F(__is_bounded_array(cvoid*))];
+}

aaron.ballman wrote:
> Any reason there's not a test with something like `int[10]` and `int[]`? 
> (Same below.)
Those are `IntAr` and `IntArNB` at the very top. I can rename those if you'd 
like.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D116280

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


[PATCH] D116280: [clang] adds unary type trait checks as compiler built-ins

2022-04-18 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added inline comments.



Comment at: clang/test/SemaCXX/type-traits.cpp:764
+  int t30[F(__is_bounded_array(void*))];
+  int t31[F(__is_bounded_array(cvoid*))];
+}

aaron.ballman wrote:
> cjdb wrote:
> > aaron.ballman wrote:
> > > Any reason there's not a test with something like `int[10]` and `int[]`? 
> > > (Same below.)
> > Those are `IntAr` and `IntArNB` at the very top. I can rename those if 
> > you'd like.
> Oh, yeah, I totally missed that, thank you!
> 
> Up to you on the rename, so long as we have the coverage, that's the crucial 
> bit.
Would you be against a patch where I found and replaced **all** `TypeAr` with 
`Type[2]` and `TypeArNB` with `Type[]`? I've done several double takes myself 
and question the readability of `TypeAr`.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D116280

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


[PATCH] D119670: [clang] Warn on unqualified calls to std::move and std::forward

2022-02-13 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added a comment.

Thanks for working on this! I'm overall very happy, but I don't see a test case 
for a unary `move` originating from another namespace.




Comment at: clang/lib/Sema/SemaExpr.cpp:6422
+static void DiagnosedUnqualifiedCallsToStdFunctions(Sema &S, CallExpr *Call) {
+  // We are only checking move and forward so exit early here
+  if (Call->getNumArgs() != 1)





Comment at: clang/lib/Sema/SemaExpr.cpp:6442
+  static constexpr llvm::StringRef SpecialFunctions[] = {"move", "forward"};
+  auto it = std::find(std::begin(SpecialFunctions), std::end(SpecialFunctions),
+  D->getName());

There's a range-based `llvm::find` in `llvm/STLExtras.h`.



Comment at: clang/test/SemaCXX/warn-self-move.cpp:19
 
   using std::move;
+  x = move(x); // expected-warning{{explicitly moving}} \

Perhaps this should warn if the algorithm `std::move` isn't seen by the 
compiler (that isn't a request for this patch).



Comment at: clang/test/SemaCXX/warn-self-move.cpp:20-21
   using std::move;
-  x = move(x);  // expected-warning{{explicitly moving}}
+  x = move(x); // expected-warning{{explicitly moving}} \
+   expected-warning {{unqualified call to std::move}}
 }

Rationale: there's less mental gymnastics when backslashes aren't involved.



Comment at: clang/test/SemaCXX/warn-self-move.cpp:30-31
   using std::move;
-  global = move(global);  // expected-warning{{explicitly moving}}
+  global = move(global); // expected-warning{{explicitly moving}} \
+ expected-warning {{unqualified call to std::move}}
 }




Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119670

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


[PATCH] D119806: [clangd][NFC] includes missing headers

2022-02-14 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb created this revision.
cjdb added a reviewer: sammccall.
Herald added subscribers: usaxena95, kadircet, arphaman.
cjdb requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

`Shutdown.h` was transitively depending on two headers, but this isn't
allowed under a modules build, so they're now explicitly included.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D119806

Files:
  clang-tools-extra/clangd/support/Shutdown.h


Index: clang-tools-extra/clangd/support/Shutdown.h
===
--- clang-tools-extra/clangd/support/Shutdown.h
+++ clang-tools-extra/clangd/support/Shutdown.h
@@ -45,6 +45,8 @@
 
 #include 
 #include 
+#include 
+#include 
 
 namespace clang {
 namespace clangd {


Index: clang-tools-extra/clangd/support/Shutdown.h
===
--- clang-tools-extra/clangd/support/Shutdown.h
+++ clang-tools-extra/clangd/support/Shutdown.h
@@ -45,6 +45,8 @@
 
 #include 
 #include 
+#include 
+#include 
 
 namespace clang {
 namespace clangd {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D119806: [clangd][NFC] includes missing headers

2022-02-15 Thread Christopher Di Bella via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGd7b1c840ba4e: [clangd][NFC] includes missing headers 
(authored by cjdb).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119806

Files:
  clang-tools-extra/clangd/support/Shutdown.h


Index: clang-tools-extra/clangd/support/Shutdown.h
===
--- clang-tools-extra/clangd/support/Shutdown.h
+++ clang-tools-extra/clangd/support/Shutdown.h
@@ -45,6 +45,8 @@
 
 #include 
 #include 
+#include 
+#include 
 
 namespace clang {
 namespace clangd {


Index: clang-tools-extra/clangd/support/Shutdown.h
===
--- clang-tools-extra/clangd/support/Shutdown.h
+++ clang-tools-extra/clangd/support/Shutdown.h
@@ -45,6 +45,8 @@
 
 #include 
 #include 
+#include 
+#include 
 
 namespace clang {
 namespace clangd {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D123885: Revert "Revert "Revert "[clang][pp] adds '#pragma include_instead'"""

2022-04-22 Thread Christopher Di Bella 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 rGe9a902c7f755: Revert "Revert "Revert 
"[clang][pp] adds '#pragma include_instead'""" 
(authored by cjdb).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D123885

Files:
  clang-tools-extra/clangd/Selection.cpp
  clang-tools-extra/pseudo/lib/Lex.cpp
  clang/include/clang/Basic/DiagnosticLexKinds.td
  clang/include/clang/Basic/SourceManager.h
  clang/include/clang/Lex/HeaderSearch.h
  clang/include/clang/Lex/Lexer.h
  clang/include/clang/Lex/Preprocessor.h
  clang/include/clang/Lex/PreprocessorLexer.h
  clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
  clang/lib/Lex/Lexer.cpp
  clang/lib/Lex/PPDirectives.cpp
  clang/lib/Lex/PPLexerChange.cpp
  clang/lib/Lex/Pragma.cpp
  clang/test/PCH/ms-pch-macro-include_instead-regression.c
  clang/test/Preprocessor/Inputs/include_instead/bad-syntax.h
  clang/test/Preprocessor/Inputs/include_instead/file-not-found.h
  clang/test/Preprocessor/Inputs/include_instead/non-system-header.h
  clang/test/Preprocessor/Inputs/include_instead/private-x.h
  clang/test/Preprocessor/Inputs/include_instead/private1.h
  clang/test/Preprocessor/Inputs/include_instead/private2.h
  clang/test/Preprocessor/Inputs/include_instead/private3.h
  clang/test/Preprocessor/Inputs/include_instead/public-after.h
  clang/test/Preprocessor/Inputs/include_instead/public-before.h
  clang/test/Preprocessor/Inputs/include_instead/public-empty.h
  clang/test/Preprocessor/include_instead.cpp
  clang/test/Preprocessor/include_instead_file_not_found.cpp

Index: clang/test/Preprocessor/include_instead_file_not_found.cpp
===
--- clang/test/Preprocessor/include_instead_file_not_found.cpp
+++ /dev/null
@@ -1,2 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -I %S/Inputs %s
-#include 
Index: clang/test/Preprocessor/include_instead.cpp
===
--- clang/test/Preprocessor/include_instead.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -I %S/Inputs %s
-
-#include 
-#include 
-
-#include 
-// expected-error@-1{{header '' is an implementation detail; #include '' instead}}
-
-#include "include_instead/private2.h"
-// expected-error@-1{{header '"include_instead/private2.h"' is an implementation detail; #include either '' or '"include_instead/public-after.h"' instead}}
-
-#include 
-// expected-error@-1{{header '' is an implementation detail; #include one of {'', '', '"include_instead/public-before.h"'} instead}}
-
-#include 
-#include 
Index: clang/test/Preprocessor/Inputs/include_instead/public-empty.h
===
--- clang/test/Preprocessor/Inputs/include_instead/public-empty.h
+++ /dev/null
@@ -1 +0,0 @@
-// This file simply needs to exist.
Index: clang/test/Preprocessor/Inputs/include_instead/public-before.h
===
--- clang/test/Preprocessor/Inputs/include_instead/public-before.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#pragma GCC system_header
-
-#include  // no warning expected
-#include  // no warning expected
-#include  // no warning expected
Index: clang/test/Preprocessor/Inputs/include_instead/public-after.h
===
--- clang/test/Preprocessor/Inputs/include_instead/public-after.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#include 
-#pragma GCC system_header
Index: clang/test/Preprocessor/Inputs/include_instead/private3.h
===
--- clang/test/Preprocessor/Inputs/include_instead/private3.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#pragma GCC system_header
-
-#pragma clang include_instead()
-#pragma clang include_instead()
-#pragma clang include_instead("include_instead/public-before.h")
Index: clang/test/Preprocessor/Inputs/include_instead/private2.h
===
--- clang/test/Preprocessor/Inputs/include_instead/private2.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#pragma GCC system_header
-
-#pragma clang include_instead()
-#pragma clang include_instead("include_instead/public-after.h")
Index: clang/test/Preprocessor/Inputs/include_instead/private1.h
===
--- clang/test/Preprocessor/Inputs/include_instead/private1.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#pragma GCC system_header
-#pragma clang include_instead()
Index: clang/test/Preprocessor/Inputs/include_instead/private-x.h
===
--- clang/test/Preprocessor/Inputs/include_instead/private-x.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#include 
-
-#pragma GCC system_header
-#pragma clang include_instead()
Index: clang/test/Pre

[PATCH] D116280: [clang] adds unary type trait checks as compiler built-ins

2022-04-22 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb updated this revision to Diff 424672.
cjdb marked 5 inline comments as done.
cjdb edited the summary of this revision.
cjdb added a comment.

- handles VLAs
- adds `__is_referenceable` which is used by portions of the standard library


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D116280

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/lib/Sema/SemaType.cpp
  clang/test/SemaCXX/type-traits.cpp

Index: clang/test/SemaCXX/type-traits.cpp
===
--- clang/test/SemaCXX/type-traits.cpp
+++ clang/test/SemaCXX/type-traits.cpp
@@ -345,11 +345,19 @@
 }
 
 typedef Enum EnumType;
+typedef EnumClass EnumClassType;
 
 void is_enum()
 {
   { int arr[T(__is_enum(Enum))]; }
   { int arr[T(__is_enum(EnumType))]; }
+  { int arr[T(__is_enum(SignedEnum))]; }
+  { int arr[T(__is_enum(UnsignedEnum))]; }
+
+  { int arr[T(__is_enum(EnumClass))]; }
+  { int arr[T(__is_enum(EnumClassType))]; }
+  { int arr[T(__is_enum(SignedEnumClass))]; }
+  { int arr[T(__is_enum(UnsignedEnumClass))]; }
 
   { int arr[F(__is_enum(int))]; }
   { int arr[F(__is_enum(Union))]; }
@@ -363,6 +371,29 @@
   { int arr[F(__is_enum(HasAnonymousUnion))]; }
 }
 
+void is_scoped_enum() {
+  { int arr[F(__is_scoped_enum(Enum))]; }
+  { int arr[F(__is_scoped_enum(EnumType))]; }
+  { int arr[F(__is_scoped_enum(SignedEnum))]; }
+  { int arr[F(__is_scoped_enum(UnsignedEnum))]; }
+
+  { int arr[T(__is_scoped_enum(EnumClass))]; }
+  { int arr[T(__is_scoped_enum(EnumClassType))]; }
+  { int arr[T(__is_scoped_enum(SignedEnumClass))]; }
+  { int arr[T(__is_scoped_enum(UnsignedEnumClass))]; }
+
+  { int arr[F(__is_scoped_enum(int))]; }
+  { int arr[F(__is_scoped_enum(Union))]; }
+  { int arr[F(__is_scoped_enum(Int))]; }
+  { int arr[F(__is_scoped_enum(IntAr))]; }
+  { int arr[F(__is_scoped_enum(UnionAr))]; }
+  { int arr[F(__is_scoped_enum(Derives))]; }
+  { int arr[F(__is_scoped_enum(ClassType))]; }
+  { int arr[F(__is_scoped_enum(cvoid))]; }
+  { int arr[F(__is_scoped_enum(IntArNB))]; }
+  { int arr[F(__is_scoped_enum(HasAnonymousUnion))]; }
+}
+
 struct FinalClass final {
 };
 
@@ -702,6 +733,106 @@
   int t31[F(__is_array(cvoid*))];
 }
 
+void is_bounded_array(int n) {
+  int t01[T(__is_bounded_array(IntAr))];
+  int t02[F(__is_bounded_array(IntArNB))];
+  int t03[T(__is_bounded_array(UnionAr))];
+
+  int t10[F(__is_bounded_array(void))];
+  int t11[F(__is_bounded_array(cvoid))];
+  int t12[F(__is_bounded_array(float))];
+  int t13[F(__is_bounded_array(double))];
+  int t14[F(__is_bounded_array(long double))];
+  int t15[F(__is_bounded_array(bool))];
+  int t16[F(__is_bounded_array(char))];
+  int t17[F(__is_bounded_array(signed char))];
+  int t18[F(__is_bounded_array(unsigned char))];
+  int t19[F(__is_bounded_array(wchar_t))];
+  int t20[F(__is_bounded_array(short))];
+  int t21[F(__is_bounded_array(unsigned short))];
+  int t22[F(__is_bounded_array(int))];
+  int t23[F(__is_bounded_array(unsigned int))];
+  int t24[F(__is_bounded_array(long))];
+  int t25[F(__is_bounded_array(unsigned long))];
+  int t26[F(__is_bounded_array(Union))];
+  int t27[F(__is_bounded_array(Derives))];
+  int t28[F(__is_bounded_array(ClassType))];
+  int t29[F(__is_bounded_array(Enum))];
+  int t30[F(__is_bounded_array(void *))];
+  int t31[F(__is_bounded_array(cvoid *))];
+
+  int t32[n];
+  (void)__is_bounded_array(decltype(t32)); // expected-error{{variable length arrays are not supported for '__is_bounded_array'}}
+}
+
+void is_unbounded_array(int n) {
+  int t01[F(__is_unbounded_array(IntAr))];
+  int t02[T(__is_unbounded_array(IntArNB))];
+  int t03[F(__is_unbounded_array(UnionAr))];
+
+  int t10[F(__is_unbounded_array(void))];
+  int t11[F(__is_unbounded_array(cvoid))];
+  int t12[F(__is_unbounded_array(float))];
+  int t13[F(__is_unbounded_array(double))];
+  int t14[F(__is_unbounded_array(long double))];
+  int t15[F(__is_unbounded_array(bool))];
+  int t16[F(__is_unbounded_array(char))];
+  int t17[F(__is_unbounded_array(signed char))];
+  int t18[F(__is_unbounded_array(unsigned char))];
+  int t19[F(__is_unbounded_array(wchar_t))];
+  int t20[F(__is_unbounded_array(short))];
+  int t21[F(__is_unbounded_array(unsigned short))];
+  int t22[F(__is_unbounded_array(int))];
+  int t23[F(__is_unbounded_array(unsigned int))];
+  int t24[F(__is_unbounded_array(long))];
+  int t25[F(__is_unbounded_array(unsigned long))];
+  int t26[F(__is_unbounded_array(Union))];
+  int t27[F(__is_unbounded_array(Derives))];
+  int t28[F(__is_unbounded_array(ClassType))];
+  int t29[F(__is_unbounded_array(Enum))];
+  int t30[F(__is_unbounded_array(void *))];
+  int t31[F(__is_unbounded_array(cvoid *))];
+
+  int t32[n];
+  (void)__is_unbounded_array(decltype(t32

[PATCH] D116280: [clang] adds unary type trait checks as compiler built-ins

2022-04-22 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb updated this revision to Diff 424673.
cjdb added a comment.

fixes formatting


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D116280

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/lib/Sema/SemaType.cpp
  clang/test/SemaCXX/type-traits.cpp

Index: clang/test/SemaCXX/type-traits.cpp
===
--- clang/test/SemaCXX/type-traits.cpp
+++ clang/test/SemaCXX/type-traits.cpp
@@ -345,11 +345,19 @@
 }
 
 typedef Enum EnumType;
+typedef EnumClass EnumClassType;
 
 void is_enum()
 {
   { int arr[T(__is_enum(Enum))]; }
   { int arr[T(__is_enum(EnumType))]; }
+  { int arr[T(__is_enum(SignedEnum))]; }
+  { int arr[T(__is_enum(UnsignedEnum))]; }
+
+  { int arr[T(__is_enum(EnumClass))]; }
+  { int arr[T(__is_enum(EnumClassType))]; }
+  { int arr[T(__is_enum(SignedEnumClass))]; }
+  { int arr[T(__is_enum(UnsignedEnumClass))]; }
 
   { int arr[F(__is_enum(int))]; }
   { int arr[F(__is_enum(Union))]; }
@@ -363,6 +371,29 @@
   { int arr[F(__is_enum(HasAnonymousUnion))]; }
 }
 
+void is_scoped_enum() {
+  { int arr[F(__is_scoped_enum(Enum))]; }
+  { int arr[F(__is_scoped_enum(EnumType))]; }
+  { int arr[F(__is_scoped_enum(SignedEnum))]; }
+  { int arr[F(__is_scoped_enum(UnsignedEnum))]; }
+
+  { int arr[T(__is_scoped_enum(EnumClass))]; }
+  { int arr[T(__is_scoped_enum(EnumClassType))]; }
+  { int arr[T(__is_scoped_enum(SignedEnumClass))]; }
+  { int arr[T(__is_scoped_enum(UnsignedEnumClass))]; }
+
+  { int arr[F(__is_scoped_enum(int))]; }
+  { int arr[F(__is_scoped_enum(Union))]; }
+  { int arr[F(__is_scoped_enum(Int))]; }
+  { int arr[F(__is_scoped_enum(IntAr))]; }
+  { int arr[F(__is_scoped_enum(UnionAr))]; }
+  { int arr[F(__is_scoped_enum(Derives))]; }
+  { int arr[F(__is_scoped_enum(ClassType))]; }
+  { int arr[F(__is_scoped_enum(cvoid))]; }
+  { int arr[F(__is_scoped_enum(IntArNB))]; }
+  { int arr[F(__is_scoped_enum(HasAnonymousUnion))]; }
+}
+
 struct FinalClass final {
 };
 
@@ -702,6 +733,106 @@
   int t31[F(__is_array(cvoid*))];
 }
 
+void is_bounded_array(int n) {
+  int t01[T(__is_bounded_array(IntAr))];
+  int t02[F(__is_bounded_array(IntArNB))];
+  int t03[T(__is_bounded_array(UnionAr))];
+
+  int t10[F(__is_bounded_array(void))];
+  int t11[F(__is_bounded_array(cvoid))];
+  int t12[F(__is_bounded_array(float))];
+  int t13[F(__is_bounded_array(double))];
+  int t14[F(__is_bounded_array(long double))];
+  int t15[F(__is_bounded_array(bool))];
+  int t16[F(__is_bounded_array(char))];
+  int t17[F(__is_bounded_array(signed char))];
+  int t18[F(__is_bounded_array(unsigned char))];
+  int t19[F(__is_bounded_array(wchar_t))];
+  int t20[F(__is_bounded_array(short))];
+  int t21[F(__is_bounded_array(unsigned short))];
+  int t22[F(__is_bounded_array(int))];
+  int t23[F(__is_bounded_array(unsigned int))];
+  int t24[F(__is_bounded_array(long))];
+  int t25[F(__is_bounded_array(unsigned long))];
+  int t26[F(__is_bounded_array(Union))];
+  int t27[F(__is_bounded_array(Derives))];
+  int t28[F(__is_bounded_array(ClassType))];
+  int t29[F(__is_bounded_array(Enum))];
+  int t30[F(__is_bounded_array(void *))];
+  int t31[F(__is_bounded_array(cvoid *))];
+
+  int t32[n];
+  (void)__is_bounded_array(decltype(t32)); // expected-error{{variable length arrays are not supported for '__is_bounded_array'}}
+}
+
+void is_unbounded_array(int n) {
+  int t01[F(__is_unbounded_array(IntAr))];
+  int t02[T(__is_unbounded_array(IntArNB))];
+  int t03[F(__is_unbounded_array(UnionAr))];
+
+  int t10[F(__is_unbounded_array(void))];
+  int t11[F(__is_unbounded_array(cvoid))];
+  int t12[F(__is_unbounded_array(float))];
+  int t13[F(__is_unbounded_array(double))];
+  int t14[F(__is_unbounded_array(long double))];
+  int t15[F(__is_unbounded_array(bool))];
+  int t16[F(__is_unbounded_array(char))];
+  int t17[F(__is_unbounded_array(signed char))];
+  int t18[F(__is_unbounded_array(unsigned char))];
+  int t19[F(__is_unbounded_array(wchar_t))];
+  int t20[F(__is_unbounded_array(short))];
+  int t21[F(__is_unbounded_array(unsigned short))];
+  int t22[F(__is_unbounded_array(int))];
+  int t23[F(__is_unbounded_array(unsigned int))];
+  int t24[F(__is_unbounded_array(long))];
+  int t25[F(__is_unbounded_array(unsigned long))];
+  int t26[F(__is_unbounded_array(Union))];
+  int t27[F(__is_unbounded_array(Derives))];
+  int t28[F(__is_unbounded_array(ClassType))];
+  int t29[F(__is_unbounded_array(Enum))];
+  int t30[F(__is_unbounded_array(void *))];
+  int t31[F(__is_unbounded_array(cvoid *))];
+
+  int t32[n];
+  (void)__is_unbounded_array(decltype(t32)); // expected-error{{variable length arrays are not supported for '__is_unbounded_array'}}
+}
+
+void is_referenceable() {
+  { int a[T(__is_referenceable(

[PATCH] D124726: Suggest typoed directives in preprocessor conditionals

2022-05-06 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added a comment.

Thanks for working on this!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D124726

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


[PATCH] D129538: [clang] adds prototype for being able to alternate diagnostic formats

2022-07-11 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb created this revision.
cjdb added a reviewer: aaron.ballman.
Herald added a project: All.
cjdb requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

In an effort to move from unstructured text diagnostics to structured
diagnostics, while keeping support for the existing model, we need to
introduce a way to hotswap between the desired modes. The visitor
pattern is a natural ally here because it allows us to defer logic to
handlers that know the specifics of the diagnostic without cluttering
the compiler's logic.

There are two parts to the design: `BasicDiagnostic`, which is used as
an abstract base for errors, warnings, and remarks; and
`DiagnosticContext`, which is used as an abstract base for notes. We've
split diagnostics into these two categories so that it's possible for to
enrich diagnostics with multiple unrelated contexts (notes seem to trail
diagnostics in a detatched and unherded fashion). FixIts are a form of
diagnostic context.

Although parts of `BasicDiagnostic` and `DiagnosticContext` should be
generated via TableGen, we're initially implementing everything manually
so that we can prototype what is necessary: it will be far easier to do
this with a handful of diagnostics than to also figure out how to
integrate this into TableGen at the same time.

**Reviewers should note that testing is currently lacking. Tests for the
diagnostic framework seem to be nonexistent; this should probably
change.**

Depends on: D109701 


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D129538

Files:
  clang/include/clang/Basic/Diagnostic.h
  clang/include/clang/Sema/Sema.h
  clang/unittests/Basic/SarifTest.cpp

Index: clang/unittests/Basic/SarifTest.cpp
===
--- clang/unittests/Basic/SarifTest.cpp
+++ clang/unittests/Basic/SarifTest.cpp
@@ -317,4 +317,20 @@
   ASSERT_THAT(Output, ::testing::StrEq(ExpectedOutput));
 }
 
+// Check that we can set/get a SarifDocumentWriter from the DiagnosticsEngine
+// Note that there doesn't appear to be any tests for the DiagnosticsEngine, so
+// we test here.
+TEST_F(SarifDocumentWriterTest, checkDiagnosticsEngineSetAndGet) {
+  ASSERT_FALSE(Diags.getSarifWriter());
+
+  // GIVEN:
+  SarifDocumentWriter Writer(SourceMgr);
+
+  // WHEN: the DiagnosticsEngine is set
+  Diags.setSarifWriter(&Writer);
+
+  // THEN: the DiagnosticsEngine points to the local SarifDocumentWriter
+  EXPECT_TRUE(Diags.getSarifWriter() == &Writer);
+}
+
 } // namespace
Index: clang/include/clang/Sema/Sema.h
===
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -38,6 +38,7 @@
 #include "clang/Basic/BitmaskEnum.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/DarwinSDKInfo.h"
+#include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/ExpressionTraits.h"
 #include "clang/Basic/Module.h"
 #include "clang/Basic/OpenCLOptions.h"
@@ -1772,6 +1773,14 @@
   return Diag;
 }
 
+const SemaDiagnosticBuilder &operator<<(const BasicDiagnostic &Diag) const {
+  if (SarifDocumentWriter *W = S.Diags.getSarifWriter())
+Diag.EmitSarifDiagnostic(*W);
+  else
+Diag.EmitTraditionalDiagnostic();
+  return *this;
+}
+
 // It is necessary to limit this to rvalue reference to avoid calling this
 // function with a bitfield lvalue argument since non-const reference to
 // bitfield is not allowed.
@@ -13584,6 +13593,28 @@
  llvm::StringRef StackSlotLabel,
  AlignPackInfo Value);
 
+class SemaDiagnostic : public BasicDiagnostic {
+protected:
+  SemaDiagnostic(DiagID ID, Sema& S)
+  : BasicDiagnostic(ID)
+  , S(&S)
+  {}
+
+  Sema& getSema() const { return *S; }
+private:
+  Sema* S;
+};
+
+class SemaDiagnosticContext : public DiagnosticContext {
+protected:
+  explicit SemaDiagnosticContext(Sema& S)
+  : S(&S)
+  {}
+
+  Sema& getSema() const { return *S; }
+private:
+  Sema* S;
+};
 } // end namespace clang
 
 namespace llvm {
Index: clang/include/clang/Basic/Diagnostic.h
===
--- clang/include/clang/Basic/Diagnostic.h
+++ clang/include/clang/Basic/Diagnostic.h
@@ -16,6 +16,7 @@
 
 #include "clang/Basic/DiagnosticIDs.h"
 #include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/Sarif.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/Specifiers.h"
 #include "llvm/ADT/ArrayRef.h"
@@ -183,6 +184,45 @@
   DiagnosticStorage() = default;
 };
 
+/// Abstract interface for all errors, warnings, and remarks. This allows us to
+/// use the visitor pattern. This is something that will be concretely defined
+/// in the short-term, as we experiment, but will be migrated over to TableGen
+/// after a few diagnostics have been implemented.
+c

[PATCH] D129538: [clang] adds prototype for being able to alternate diagnostic formats

2022-07-11 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb updated this revision to Diff 443833.
cjdb added a comment.

`arc diff` no longer seems to autoformat


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D129538

Files:
  clang/include/clang/Basic/Diagnostic.h
  clang/include/clang/Sema/Sema.h
  clang/unittests/Basic/SarifTest.cpp

Index: clang/unittests/Basic/SarifTest.cpp
===
--- clang/unittests/Basic/SarifTest.cpp
+++ clang/unittests/Basic/SarifTest.cpp
@@ -317,4 +317,20 @@
   ASSERT_THAT(Output, ::testing::StrEq(ExpectedOutput));
 }
 
+// Check that we can set/get a SarifDocumentWriter from the DiagnosticsEngine
+// Note that there doesn't appear to be any tests for the DiagnosticsEngine, so
+// we test here.
+TEST_F(SarifDocumentWriterTest, checkDiagnosticsEngineSetAndGet) {
+  ASSERT_FALSE(Diags.getSarifWriter());
+
+  // GIVEN:
+  SarifDocumentWriter Writer(SourceMgr);
+
+  // WHEN: the DiagnosticsEngine is set
+  Diags.setSarifWriter(&Writer);
+
+  // THEN: the DiagnosticsEngine points to the local SarifDocumentWriter
+  EXPECT_TRUE(Diags.getSarifWriter() == &Writer);
+}
+
 } // namespace
Index: clang/include/clang/Sema/Sema.h
===
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -38,6 +38,7 @@
 #include "clang/Basic/BitmaskEnum.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/DarwinSDKInfo.h"
+#include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/ExpressionTraits.h"
 #include "clang/Basic/Module.h"
 #include "clang/Basic/OpenCLOptions.h"
@@ -1772,6 +1773,14 @@
   return Diag;
 }
 
+const SemaDiagnosticBuilder &operator<<(const BasicDiagnostic &Diag) const {
+  if (SarifDocumentWriter *W = S.Diags.getSarifWriter())
+Diag.EmitSarifDiagnostic(*W);
+  else
+Diag.EmitTraditionalDiagnostic();
+  return *this;
+}
+
 // It is necessary to limit this to rvalue reference to avoid calling this
 // function with a bitfield lvalue argument since non-const reference to
 // bitfield is not allowed.
@@ -13583,7 +13592,6 @@
  PragmaMsStackAction Action,
  llvm::StringRef StackSlotLabel,
  AlignPackInfo Value);
-
 } // end namespace clang
 
 namespace llvm {
Index: clang/include/clang/Basic/Diagnostic.h
===
--- clang/include/clang/Basic/Diagnostic.h
+++ clang/include/clang/Basic/Diagnostic.h
@@ -16,6 +16,7 @@
 
 #include "clang/Basic/DiagnosticIDs.h"
 #include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/Sarif.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/Specifiers.h"
 #include "llvm/ADT/ArrayRef.h"
@@ -183,6 +184,45 @@
   DiagnosticStorage() = default;
 };
 
+/// Abstract interface for all errors, warnings, and remarks. This allows us to
+/// use the visitor pattern. This is something that will be concretely defined
+/// in the short-term, as we experiment, but will be migrated over to TableGen
+/// after a few diagnostics have been implemented.
+class BasicDiagnostic {
+public:
+  virtual ~BasicDiagnostic() = default;
+
+  /// Emits the diagnostic as Clang's original unstructured text format.
+  virtual void EmitTraditionalDiagnostic() const = 0;
+
+  /// Emits the diagnostic as SARIF.
+  virtual void EmitSarifDiagnostic(SarifDocumentWriter &) const = 0;
+
+protected:
+  using DiagID = unsigned;
+
+  explicit BasicDiagnostic(DiagID K) : ID(K) {}
+
+  DiagID getID() const { return ID; }
+
+private:
+  DiagID ID;
+};
+
+/// Abstract interface for diagnostic contexts (traditionally: notes).
+/// A BasicDiagnostic may have as many different contexts as required to provide
+/// users with a complete picture.
+class DiagnosticContext {
+public:
+  virtual ~DiagnosticContext() = default;
+
+  /// Emits the diagnostic as an unstructured text note.
+  virtual void EmitTraditionalNote() const = 0;
+
+  /// Emits the diagnostic as SARIF.
+  virtual void EmitSarifContext(SarifDocumentWriter &) const = 0;
+};
+
 /// Concrete class used by the front-end to report problems and issues.
 ///
 /// This massages the diagnostics (e.g. handling things like "report warnings
@@ -295,6 +335,7 @@
   DiagnosticConsumer *Client = nullptr;
   std::unique_ptr Owner;
   SourceManager *SourceMgr = nullptr;
+  SarifDocumentWriter *SarifWriter = nullptr;
 
   /// Mapping information for diagnostics.
   ///
@@ -979,6 +1020,9 @@
   /// Return the value associated with this diagnostic flag.
   StringRef getFlagValue() const { return FlagValue; }
 
+  void setSarifWriter(SarifDocumentWriter *W) { SarifWriter = W; }
+  SarifDocumentWriter *getSarifWriter() const { return SarifWriter; }
+
 private:
   // This is private state used by DiagnosticBuilder.  We 

[PATCH] D129835: [clang] adds a discardable attribute

2022-07-14 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb created this revision.
cjdb added a reviewer: aaron.ballman.
Herald added a subscriber: jdoerfert.
Herald added a project: All.
cjdb requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Although the default behaviour for C and C++ is to not diagnose ignored function
calls, we can make this the default by using `#pragma clang attribute
push([[nodiscard]],  apply_to = function)`. When we have a function that can
have its value discarded, we can use `[[clang::discardable]]` to indicate that
the ``[[nodiscard]]`` attribute should be ignored.

`[[clang::discardable]]` can be placed anywhere `[[nodiscard]]` is allowed,
but the presence of either is prioritised when it's applied to a callable.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D129835

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/AST/Expr.h
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/lib/AST/Expr.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/lib/Sema/SemaStmt.cpp
  clang/test/Misc/pragma-attribute-supported-attributes-list.test
  clang/test/SemaCXX/discardable.cpp

Index: clang/test/SemaCXX/discardable.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/discardable.cpp
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -fsyntax-only -Wunknown-attributes -verify -std=c++17 %s
+
+[[clang::discardable]] int without_nodiscard();
+
+[[nodiscard, clang::discardable]] int no_warn_fundamental();
+
+struct naked {};
+[[nodiscard, clang::discardable]] naked no_warn_class_type();
+[[nodiscard, clang::discardable]] naked* no_warn_pointer();
+[[nodiscard, clang::discardable]] naked& no_warn_reference();
+
+struct [[nodiscard]] nodiscard_type {};
+[[clang::discardable]] nodiscard_type no_warn_function_override();
+
+struct [[clang::discardable]] discardable_type {};
+discardable_type no_warn_discardable_type();
+[[nodiscard]] discardable_type warns_function_override();
+
+struct [[nodiscard, clang::discardable]] discardable_type2 {};
+discardable_type2 no_warn_discardable_type2();
+
+struct discardable_members {
+  [[nodiscard, clang::discardable]] discardable_members(int);
+  [[nodiscard, clang::discardable]] int f() const;
+};
+
+void test_expression_statements() {
+  without_nodiscard();
+
+  no_warn_fundamental();
+
+  no_warn_class_type();
+  no_warn_pointer();
+  no_warn_reference();
+
+  no_warn_function_override();
+
+  no_warn_discardable_type();
+  warns_function_override(); // expected-warning{{ignoring return value}}
+
+  no_warn_discardable_type2();
+
+  discardable_members(0);
+  discardable_members(0).f();
+}
Index: clang/test/Misc/pragma-attribute-supported-attributes-list.test
===
--- clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -60,6 +60,7 @@
 // CHECK-NEXT: DiagnoseAsBuiltin (SubjectMatchRule_function)
 // CHECK-NEXT: DisableSanitizerInstrumentation (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_variable_is_global)
 // CHECK-NEXT: DisableTailCalls (SubjectMatchRule_function, SubjectMatchRule_objc_method)
+// CHECK-NEXT: DisableWarnUnusedResult (SubjectMatchRule_objc_method, SubjectMatchRule_enum, SubjectMatchRule_record, SubjectMatchRule_hasType_functionType, SubjectMatchRule_type_alias)
 // CHECK-NEXT: EnableIf (SubjectMatchRule_function)
 // CHECK-NEXT: EnforceTCB (SubjectMatchRule_function, SubjectMatchRule_objc_method)
 // CHECK-NEXT: EnforceTCBLeaf (SubjectMatchRule_function, SubjectMatchRule_objc_method)
Index: clang/lib/Sema/SemaStmt.cpp
===
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -282,8 +282,12 @@
 if (E->getType()->isVoidType())
   return;
 
-if (DiagnoseNoDiscard(*this, cast_or_null(
- CE->getUnusedResultAttr(Context)),
+if (CE->getDisableUnusedResultAttr(Context))
+  return;
+
+if (DiagnoseNoDiscard(*this,
+  cast_or_null(
+  CE->getUnusedResultAttr(Context)),
   Loc, R1, R2, /*isCtor=*/false))
   return;
 
@@ -305,6 +309,11 @@
 }
   } else if (const auto *CE = dyn_cast(E)) {
 if (const CXXConstructorDecl *Ctor = CE->getConstructor()) {
+  const auto *D = Ctor->getAttr();
+  D = D ? D : Ctor->getParent()->getAttr();
+  if (D)
+return;
+
   const auto *A = Ctor->getAttr();
   A = A ? A : Ctor->getParent()->getAttr();
   if (DiagnoseNoDiscard(*this, A, Loc, R1, R2, /*isCtor=*/true))
@@ -312,6 +321,8 @@
 }
   } else if (const auto *ILE = dyn_cast(E)) {
 if (const TagDecl *TD = ILE->getType()->getAsTagDecl()) {
+  if (TD->getAttr())
+return;
 
   if (DiagnoseNoDiscard(*this, TD->getAttr(), Loc, R1,

[PATCH] D129835: [clang] adds a discardable attribute

2022-07-14 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb updated this revision to Diff 444890.
cjdb added a comment.

undoes editor autotrimming of spaces


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D129835

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/AST/Expr.h
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/lib/AST/Expr.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/lib/Sema/SemaStmt.cpp
  clang/test/Misc/pragma-attribute-supported-attributes-list.test
  clang/test/SemaCXX/discardable.cpp

Index: clang/test/SemaCXX/discardable.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/discardable.cpp
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -fsyntax-only -Wunknown-attributes -verify -std=c++17 %s
+
+[[clang::discardable]] int without_nodiscard();
+
+[[nodiscard, clang::discardable]] int no_warn_fundamental();
+
+struct naked {};
+[[nodiscard, clang::discardable]] naked no_warn_class_type();
+[[nodiscard, clang::discardable]] naked* no_warn_pointer();
+[[nodiscard, clang::discardable]] naked& no_warn_reference();
+
+struct [[nodiscard]] nodiscard_type {};
+[[clang::discardable]] nodiscard_type no_warn_function_override();
+
+struct [[clang::discardable]] discardable_type {};
+discardable_type no_warn_discardable_type();
+[[nodiscard]] discardable_type warns_function_override();
+
+struct [[nodiscard, clang::discardable]] discardable_type2 {};
+discardable_type2 no_warn_discardable_type2();
+
+struct discardable_members {
+  [[nodiscard, clang::discardable]] discardable_members(int);
+  [[nodiscard, clang::discardable]] int f() const;
+};
+
+void test_expression_statements() {
+  without_nodiscard();
+
+  no_warn_fundamental();
+
+  no_warn_class_type();
+  no_warn_pointer();
+  no_warn_reference();
+
+  no_warn_function_override();
+
+  no_warn_discardable_type();
+  warns_function_override(); // expected-warning{{ignoring return value}}
+
+  no_warn_discardable_type2();
+
+  discardable_members(0);
+  discardable_members(0).f();
+}
Index: clang/test/Misc/pragma-attribute-supported-attributes-list.test
===
--- clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -60,6 +60,7 @@
 // CHECK-NEXT: DiagnoseAsBuiltin (SubjectMatchRule_function)
 // CHECK-NEXT: DisableSanitizerInstrumentation (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_variable_is_global)
 // CHECK-NEXT: DisableTailCalls (SubjectMatchRule_function, SubjectMatchRule_objc_method)
+// CHECK-NEXT: DisableWarnUnusedResult (SubjectMatchRule_objc_method, SubjectMatchRule_enum, SubjectMatchRule_record, SubjectMatchRule_hasType_functionType, SubjectMatchRule_type_alias)
 // CHECK-NEXT: EnableIf (SubjectMatchRule_function)
 // CHECK-NEXT: EnforceTCB (SubjectMatchRule_function, SubjectMatchRule_objc_method)
 // CHECK-NEXT: EnforceTCBLeaf (SubjectMatchRule_function, SubjectMatchRule_objc_method)
Index: clang/lib/Sema/SemaStmt.cpp
===
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -282,8 +282,12 @@
 if (E->getType()->isVoidType())
   return;
 
-if (DiagnoseNoDiscard(*this, cast_or_null(
- CE->getUnusedResultAttr(Context)),
+if (CE->getDisableUnusedResultAttr(Context))
+  return;
+
+if (DiagnoseNoDiscard(*this,
+  cast_or_null(
+  CE->getUnusedResultAttr(Context)),
   Loc, R1, R2, /*isCtor=*/false))
   return;
 
@@ -305,6 +309,11 @@
 }
   } else if (const auto *CE = dyn_cast(E)) {
 if (const CXXConstructorDecl *Ctor = CE->getConstructor()) {
+  const auto *D = Ctor->getAttr();
+  D = D ? D : Ctor->getParent()->getAttr();
+  if (D)
+return;
+
   const auto *A = Ctor->getAttr();
   A = A ? A : Ctor->getParent()->getAttr();
   if (DiagnoseNoDiscard(*this, A, Loc, R1, R2, /*isCtor=*/true))
@@ -312,6 +321,8 @@
 }
   } else if (const auto *ILE = dyn_cast(E)) {
 if (const TagDecl *TD = ILE->getType()->getAsTagDecl()) {
+  if (TD->getAttr())
+return;
 
   if (DiagnoseNoDiscard(*this, TD->getAttr(), Loc, R1,
 R2, /*isCtor=*/false))
@@ -328,6 +339,8 @@
 }
 const ObjCMethodDecl *MD = ME->getMethodDecl();
 if (MD) {
+  if (MD->getAttr())
+return;
   if (DiagnoseNoDiscard(*this, MD->getAttr(), Loc, R1,
 R2, /*isCtor=*/false))
 return;
Index: clang/lib/Sema/SemaDeclAttr.cpp
===
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -3167,6 +3167,39 @@
   D->addAttr(::new (S.Context) WarnUnusedResultAttr(S.Context, 

[PATCH] D129835: [clang] adds a discardable attribute

2022-07-15 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added a subscriber: ldionne.
cjdb added a comment.

In D129835#3655487 , @aaron.ballman 
wrote:

>> When we have a function that can have its value discarded, we can use 
>> [[clang::discardable]] to indicate that the `[[nodiscard]]` attribute should 
>> be ignored.
>
> Alternatively, you can scope the pragma and declarations appropriately and 
> then we don't need to add a new attribute. Is there a reason that wouldn't 
> work for you?

A key problem here (IMO) is that this requires manually pushing and popping the 
pragma as it is required. With `[[discardable]]` one just needs to push/pop at 
the extremes of a file (and if a future version of module maps supports global 
pragmas for a module, there too, but that's a discussion that requires a design 
doc).

It's also good for documenting "hey you can discard this thing in my sea of 
nodiscard interfaces" on the interface itself. That coupling is also good for 
correctness because it means something can't accidentally slip in/out of the 
pragma's scope.

> (This attribute would be interesting to consider if we added a feature flag 
> like `-fdiagnose-discarded-results` where the default is as-if everything was 
> declared `nodiscard` and then you could mark the APIs with 
> `[[clang::discardable]]` for the few whose results don't matter. However, 
> that's also a much bigger feature because system headers are a challenge.)

The primary reason for me wanting to add this attribute comes from my libc++ 
days, where I wanted to mark whatever made sense as nodiscard. @ldionne was in 
favour in principle, but against in practice; noting that nodiscard would 
clutter the interface too much, and it'd be better if the situation were 
reversed (which is what this patch does). I think adding this is still a good 
step for getting us to a world where `-fdiagnose-discarded-results` can be a 
real consideration, especially if libc++ and llvm-libc adopt it.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D129835

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


[PATCH] D129886: [clang] Add -fdiagnostics-format=sarif for SARIF diagnostics

2022-07-15 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added a comment.

Thanks for getting this started! To get this ready for submission, would you be 
able to add a test please?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D129886

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


[PATCH] D129951: [clang] teaches Clang the special ADL rules for functions in std::ranges

2022-07-16 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb created this revision.
cjdb added a reviewer: aaron.ballman.
Herald added a project: All.
cjdb requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Per per [range.iter.ops]/2 and [algorithms.requirements]/2, functions
declared in the namespace 'std::ranges' aren't found by ADL, and
suppress ADL when they're called in an unqualified context (e.g. a
using-directive).

Libraries have been implementing these functions as function objects
with varying rules (e.g. libc++ and Microsoft/STL both try their best to
make the function objects appear as standard library function templates,
while libstdc++ makes them plain function objects).

Having a large number of types typically has a negative impact on both
compile-times and progam size, and there are approximately 130 of these
at present. Furthermore, the diagnostics can be marginally improved by
switching to proper functions, which will make it clearer that the
problem is at the user level, rather than the implementation level (see
https://godbolt.org/z/1sYMsxdfM for an example).

By making it possible to implement ranges functions as functions, it's
hoped that the library will be incentivised to migrate over.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D129951

Files:
  clang/include/clang/AST/DeclBase.h
  clang/lib/AST/DeclBase.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/test/Sema/disable-adl.cpp

Index: clang/test/Sema/disable-adl.cpp
===
--- /dev/null
+++ clang/test/Sema/disable-adl.cpp
@@ -0,0 +1,94 @@
+// RUN: %clang_cc1 %s -fsyntax-only -verify
+
+// expected-n...@disable-adl.cpp:* 2{{}}
+
+namespace std {
+  struct S1 {};
+  S1 inhibited(S1);
+
+  namespace ranges {
+struct S2 {};
+void hidden(S2);
+int inhibited(S1);
+  }
+}
+
+void test_functions() {
+  hidden(std::ranges::S2{});
+  // expected-error@-1{{use of undeclared identifier 'hidden'; did you mean 'std::ranges::hidden'?}}
+
+  using namespace std::ranges;
+  int x = inhibited(std::S1{}); // no error
+}
+
+namespace std {
+  template
+  S1 inhibited_template(T);
+
+  namespace ranges {
+template
+void hidden_template(T);
+
+template
+int inhibited_template(T);
+  }
+}
+
+void test_function_templates() {
+  hidden_template(std::ranges::S2{});
+  // expected-error@-1{{use of undeclared identifier 'hidden_template'; did you mean 'std::ranges::hidden_template'?}}
+
+  using namespace std::ranges;
+  int x = inhibited_template(std::S1{});
+}
+
+namespace std {
+  S1 inhibited_mixed(S1);
+
+  namespace ranges {
+template
+int inhibited_mixed(T);
+  }
+}
+
+void test_mixed() {
+  using namespace std::ranges;
+  int x = inhibited_mixed(std::S1{});
+}
+
+// Should be covered by the hidden functions checks, but just to be sure.
+void test_ranges_hidden() {
+  {
+std::S1 a = inhibited(std::S1{});
+std::S1 b = inhibited_template(std::S1{});
+std::S1 c = inhibited_mixed(std::S1{});
+  }
+  {
+using namespace std;
+std::S1 a = inhibited(std::S1{});
+std::S1 b = inhibited_template(std::S1{});
+std::S1 c = inhibited_mixed(std::S1{});
+  }
+}
+
+namespace std {
+  namespace ranges {
+void operator-(S2);
+
+struct hidden_friend_operator {
+  friend void operator-(hidden_friend_operator i, int) {}
+};
+
+struct hidden_friend_swap {
+  friend void swap(hidden_friend_swap, hidden_friend_swap) {}
+};
+  }
+}
+
+void test_friends_and_operators() {
+  -std::ranges::S2{};// no error
+  std::ranges::hidden_friend_operator{} - 1; // no error
+
+  swap(std::ranges::hidden_friend_swap{}, std::ranges::hidden_friend_swap{});
+  // expected-error@-1{{use of undeclared identifier 'swap'}}
+}
Index: clang/lib/Sema/SemaOverload.cpp
===
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -9452,6 +9452,12 @@
   for (ADLResult::iterator I = Fns.begin(), E = Fns.end(); I != E; ++I) {
 DeclAccessPair FoundDecl = DeclAccessPair::make(*I, AS_none);
 
+// Functions in 'std::ranges' are hidden from ADL per [range.iter.ops]/2 and
+// [algorithms.requirements]/2.
+if ((*I)->isInStdRangesNamespace() &&
+Name.getNameKind() == DeclarationName::NameKind::Identifier)
+  continue;
+
 if (FunctionDecl *FD = dyn_cast(*I)) {
   if (ExplicitTemplateArgs)
 continue;
@@ -9650,7 +9656,7 @@
   const OverloadCandidate &Cand1,
   const OverloadCandidate &Cand2) {
   // FIXME: Per P2113R0 we also need to compare the template parameter lists
-  // when comparing template functions. 
+  // when comparing template functions.
   if (Cand1.Function && Cand2.Function && Cand1.Function->hasPrototype() &&
   Cand2.Function->hasPrototype()) {
 auto *PT1 = cast(Cand1.Function->getFunctionType())

[PATCH] D129951: [clang] teaches Clang the special ADL rules for functions in std::ranges

2022-07-16 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb updated this revision to Diff 445285.
cjdb added a comment.

moves test from Sema to SemaCXX

I Noticed that SemaCXX is only a test directory, and that there's no 
corresponding SemaCXX in either include or lib.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D129951

Files:
  clang/include/clang/AST/DeclBase.h
  clang/lib/AST/DeclBase.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/test/SemaCXX/disable-adl.cpp

Index: clang/test/SemaCXX/disable-adl.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/disable-adl.cpp
@@ -0,0 +1,94 @@
+// RUN: %clang_cc1 %s -fsyntax-only -verify
+
+// expected-n...@disable-adl.cpp:* 2{{}}
+
+namespace std {
+  struct S1 {};
+  S1 inhibited(S1);
+
+  namespace ranges {
+struct S2 {};
+void hidden(S2);
+int inhibited(S1);
+  }
+}
+
+void test_functions() {
+  hidden(std::ranges::S2{});
+  // expected-error@-1{{use of undeclared identifier 'hidden'; did you mean 'std::ranges::hidden'?}}
+
+  using namespace std::ranges;
+  int x = inhibited(std::S1{}); // no error
+}
+
+namespace std {
+  template
+  S1 inhibited_template(T);
+
+  namespace ranges {
+template
+void hidden_template(T);
+
+template
+int inhibited_template(T);
+  }
+}
+
+void test_function_templates() {
+  hidden_template(std::ranges::S2{});
+  // expected-error@-1{{use of undeclared identifier 'hidden_template'; did you mean 'std::ranges::hidden_template'?}}
+
+  using namespace std::ranges;
+  int x = inhibited_template(std::S1{});
+}
+
+namespace std {
+  S1 inhibited_mixed(S1);
+
+  namespace ranges {
+template
+int inhibited_mixed(T);
+  }
+}
+
+void test_mixed() {
+  using namespace std::ranges;
+  int x = inhibited_mixed(std::S1{});
+}
+
+// Should be covered by the hidden functions checks, but just to be sure.
+void test_ranges_hidden() {
+  {
+std::S1 a = inhibited(std::S1{});
+std::S1 b = inhibited_template(std::S1{});
+std::S1 c = inhibited_mixed(std::S1{});
+  }
+  {
+using namespace std;
+std::S1 a = inhibited(std::S1{});
+std::S1 b = inhibited_template(std::S1{});
+std::S1 c = inhibited_mixed(std::S1{});
+  }
+}
+
+namespace std {
+  namespace ranges {
+void operator-(S2);
+
+struct hidden_friend_operator {
+  friend void operator-(hidden_friend_operator i, int) {}
+};
+
+struct hidden_friend_swap {
+  friend void swap(hidden_friend_swap, hidden_friend_swap) {}
+};
+  }
+}
+
+void test_friends_and_operators() {
+  -std::ranges::S2{};// no error
+  std::ranges::hidden_friend_operator{} - 1; // no error
+
+  swap(std::ranges::hidden_friend_swap{}, std::ranges::hidden_friend_swap{});
+  // expected-error@-1{{use of undeclared identifier 'swap'}}
+}
Index: clang/lib/Sema/SemaOverload.cpp
===
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -9452,6 +9452,12 @@
   for (ADLResult::iterator I = Fns.begin(), E = Fns.end(); I != E; ++I) {
 DeclAccessPair FoundDecl = DeclAccessPair::make(*I, AS_none);
 
+// Functions in 'std::ranges' are hidden from ADL per [range.iter.ops]/2 and
+// [algorithms.requirements]/2.
+if ((*I)->isInStdRangesNamespace() &&
+Name.getNameKind() == DeclarationName::NameKind::Identifier)
+  continue;
+
 if (FunctionDecl *FD = dyn_cast(*I)) {
   if (ExplicitTemplateArgs)
 continue;
@@ -9650,7 +9656,7 @@
   const OverloadCandidate &Cand1,
   const OverloadCandidate &Cand2) {
   // FIXME: Per P2113R0 we also need to compare the template parameter lists
-  // when comparing template functions. 
+  // when comparing template functions.
   if (Cand1.Function && Cand2.Function && Cand1.Function->hasPrototype() &&
   Cand2.Function->hasPrototype()) {
 auto *PT1 = cast(Cand1.Function->getFunctionType());
@@ -12828,6 +12834,12 @@
CandidateSet, PartialOverloading,
/*KnownValid*/ true);
 
+  // Functions in 'std::ranges' inhibit ADL per [range.iter.ops]/2 and
+  // [algorithms.requirements]/2.
+  if (!ULE->decls().empty() && ULE->decls_begin()->isInStdRangesNamespace() &&
+  ULE->getName().getNameKind() == DeclarationName::NameKind::Identifier)
+return;
+
   if (ULE->requiresADL())
 AddArgumentDependentLookupCandidates(ULE->getName(), ULE->getExprLoc(),
  Args, ExplicitTemplateArgs,
Index: clang/lib/AST/DeclBase.cpp
===
--- clang/lib/AST/DeclBase.cpp
+++ clang/lib/AST/DeclBase.cpp
@@ -396,6 +396,11 @@
   return DC && DC->isStdNamespace();
 }
 
+bool Decl::isInStdRangesNamespace() const {
+  const DeclContext *DC = getDeclContext();
+  return DC && D

[PATCH] D129951: [clang] teaches Clang the special ADL rules for functions in std::ranges

2022-07-16 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb updated this revision to Diff 445286.
cjdb edited the summary of this revision.
cjdb added a comment.

updates an inaccuracy in the commit message


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D129951

Files:
  clang/include/clang/AST/DeclBase.h
  clang/lib/AST/DeclBase.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/test/SemaCXX/disable-adl.cpp

Index: clang/test/SemaCXX/disable-adl.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/disable-adl.cpp
@@ -0,0 +1,94 @@
+// RUN: %clang_cc1 %s -fsyntax-only -verify
+
+// expected-n...@disable-adl.cpp:* 2{{}}
+
+namespace std {
+  struct S1 {};
+  S1 inhibited(S1);
+
+  namespace ranges {
+struct S2 {};
+void hidden(S2);
+int inhibited(S1);
+  }
+}
+
+void test_functions() {
+  hidden(std::ranges::S2{});
+  // expected-error@-1{{use of undeclared identifier 'hidden'; did you mean 'std::ranges::hidden'?}}
+
+  using namespace std::ranges;
+  int x = inhibited(std::S1{}); // no error
+}
+
+namespace std {
+  template
+  S1 inhibited_template(T);
+
+  namespace ranges {
+template
+void hidden_template(T);
+
+template
+int inhibited_template(T);
+  }
+}
+
+void test_function_templates() {
+  hidden_template(std::ranges::S2{});
+  // expected-error@-1{{use of undeclared identifier 'hidden_template'; did you mean 'std::ranges::hidden_template'?}}
+
+  using namespace std::ranges;
+  int x = inhibited_template(std::S1{});
+}
+
+namespace std {
+  S1 inhibited_mixed(S1);
+
+  namespace ranges {
+template
+int inhibited_mixed(T);
+  }
+}
+
+void test_mixed() {
+  using namespace std::ranges;
+  int x = inhibited_mixed(std::S1{});
+}
+
+// Should be covered by the hidden functions checks, but just to be sure.
+void test_ranges_hidden() {
+  {
+std::S1 a = inhibited(std::S1{});
+std::S1 b = inhibited_template(std::S1{});
+std::S1 c = inhibited_mixed(std::S1{});
+  }
+  {
+using namespace std;
+std::S1 a = inhibited(std::S1{});
+std::S1 b = inhibited_template(std::S1{});
+std::S1 c = inhibited_mixed(std::S1{});
+  }
+}
+
+namespace std {
+  namespace ranges {
+void operator-(S2);
+
+struct hidden_friend_operator {
+  friend void operator-(hidden_friend_operator i, int) {}
+};
+
+struct hidden_friend_swap {
+  friend void swap(hidden_friend_swap, hidden_friend_swap) {}
+};
+  }
+}
+
+void test_friends_and_operators() {
+  -std::ranges::S2{};// no error
+  std::ranges::hidden_friend_operator{} - 1; // no error
+
+  swap(std::ranges::hidden_friend_swap{}, std::ranges::hidden_friend_swap{});
+  // expected-error@-1{{use of undeclared identifier 'swap'}}
+}
Index: clang/lib/Sema/SemaOverload.cpp
===
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -9452,6 +9452,12 @@
   for (ADLResult::iterator I = Fns.begin(), E = Fns.end(); I != E; ++I) {
 DeclAccessPair FoundDecl = DeclAccessPair::make(*I, AS_none);
 
+// Functions in 'std::ranges' are hidden from ADL per [range.iter.ops]/2 and
+// [algorithms.requirements]/2.
+if ((*I)->isInStdRangesNamespace() &&
+Name.getNameKind() == DeclarationName::NameKind::Identifier)
+  continue;
+
 if (FunctionDecl *FD = dyn_cast(*I)) {
   if (ExplicitTemplateArgs)
 continue;
@@ -9650,7 +9656,7 @@
   const OverloadCandidate &Cand1,
   const OverloadCandidate &Cand2) {
   // FIXME: Per P2113R0 we also need to compare the template parameter lists
-  // when comparing template functions. 
+  // when comparing template functions.
   if (Cand1.Function && Cand2.Function && Cand1.Function->hasPrototype() &&
   Cand2.Function->hasPrototype()) {
 auto *PT1 = cast(Cand1.Function->getFunctionType());
@@ -12828,6 +12834,12 @@
CandidateSet, PartialOverloading,
/*KnownValid*/ true);
 
+  // Functions in 'std::ranges' inhibit ADL per [range.iter.ops]/2 and
+  // [algorithms.requirements]/2.
+  if (!ULE->decls().empty() && ULE->decls_begin()->isInStdRangesNamespace() &&
+  ULE->getName().getNameKind() == DeclarationName::NameKind::Identifier)
+return;
+
   if (ULE->requiresADL())
 AddArgumentDependentLookupCandidates(ULE->getName(), ULE->getExprLoc(),
  Args, ExplicitTemplateArgs,
Index: clang/lib/AST/DeclBase.cpp
===
--- clang/lib/AST/DeclBase.cpp
+++ clang/lib/AST/DeclBase.cpp
@@ -396,6 +396,11 @@
   return DC && DC->isStdNamespace();
 }
 
+bool Decl::isInStdRangesNamespace() const {
+  const DeclContext *DC = getDeclContext();
+  return DC && DC->isStdRangesNamespace();
+}
+
 TranslationUnitDecl *Decl::getTr

[PATCH] D129951: [clang] teaches Clang the special ADL rules for functions in std::ranges

2022-07-16 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added a comment.

Looking at the output from Clang 14 , I'm 
observing that a binary with 178 function templates is 13% the size of the one 
with 89 function objects. When only one function object is used vs all 178 
function templates, the functions still win out, with the binary being 80% the 
size.

The AST also becomes substantially larger.

I ran `time clang++-13 -c file.cpp -std=c++20 -Oz -DNDEBUG` locally, a hundred 
times, and got the following results:

  # Function objects
  real mean:0.07447
  real median:  0.074
  real stddev:  0.002267268191

  sys mean: 0.01664
  sys median:   0.016
  sys stddev:   0.005569614534

  user mean:0.05785
  user median:  0.057
  user stddev:  0.005848896987

  # Function templates
  real mean:0.06336
  real median:  0.063
  real stddev:  0.002076905235

  sys mean: 0.01701
  sys median:   0.017
  sys stddev:   0.005545942188

  user mean:0.04645
  user median:  0.047
  user stddev:  0.005678908346


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D129951

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


[PATCH] D129951: [clang] teaches Clang the special ADL rules for functions in std::ranges

2022-07-17 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added a comment.

In D129951#3657923 , @cjdb wrote:

> ~~Looking at the output from Clang 14 , I'm 
> observing that a binary with 178 function templates is 13% the size of the 
> one with 89 function objects. When only one function object is used vs all 
> 178 function templates, the functions still win out, with the binary being 
> 80% the size.~~

I wrote this quite late at night and confused total lines of assembly with 
program size. That's not accurate at all.

There doesn't seem to be a difference between the two when the optimiser is 
enabled, but with:

- `-O0`: there's a binary size difference of 24kB.
- `-Og -g`: there's a binary size difference of 32kB.
- `-g`: there's a binary size difference of 59kB.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D129951

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


[PATCH] D129951: [clang] teaches Clang the special ADL rules for functions in std::ranges

2022-07-17 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added inline comments.



Comment at: clang/lib/Sema/SemaOverload.cpp:9438
   // FIXME: Pass in the explicit template arguments?
   ArgumentDependentLookup(Name, Loc, Args, Fns);
 

rsmith wrote:
> It would seem preferable to me to do the filtering in 
> `ArgumentDependentLookup` itself rather than here (but I don't feel strongly 
> about it).
Agreed. I tried to do it there, but was having issues getting it working. I'll 
give it a second go?



Comment at: clang/lib/Sema/SemaOverload.cpp:9455-9459
+// Functions in 'std::ranges' are hidden from ADL per [range.iter.ops]/2 
and
+// [algorithms.requirements]/2.
+if ((*I)->isInStdRangesNamespace() &&
+Name.getNameKind() == DeclarationName::NameKind::Identifier)
+  continue;

rsmith wrote:
> I worry that this might break some stdlib implementation that finds helper 
> functions via ADL in `std::ranges` somehow. Also, it seems desirable to make 
> this opt-in for the stdlib implementation and indeed for end-user functions 
> not in `std::ranges`.
> 
> Have you considered enabling this behavior with an attribute instead of by 
> detecting whether the function is in `std::ranges`?
You're the second person to have suggested this, and I daresay Aaron will too, 
based on our prior discussion about this. We'd chatted about `__disable_adl` 
specifically, so that anyone who uses it won't be affected by a silent change 
from Clang to GCC: they'd instead get a break. I would prefer an attribute too.

My main concern is that other stdlib implementers would object to adding yet 
another annotation to their function calls (based on my failure to get libc++ 
to be as aggressive as Microsoft/STL is with `[[nodiscard]]`).



Comment at: clang/lib/Sema/SemaOverload.cpp:12837-12841
+  // Functions in 'std::ranges' inhibit ADL per [range.iter.ops]/2 and
+  // [algorithms.requirements]/2.
+  if (!ULE->decls().empty() && ULE->decls_begin()->isInStdRangesNamespace() &&
+  ULE->getName().getNameKind() == DeclarationName::NameKind::Identifier)
+return;

rsmith wrote:
> What should happen if a `using` declaration names one of these things? Should 
> we care about the properties of the underlying declaration (eg, whether the 
> target of the using declaration is in this namespace / has the attribute), or 
> about the found decl (eg, whether the `using` declaration itself is in the 
> namespace / has the attribute)?
> 
> Depending on the answer, we may need to check all declarations in the 
> `UnresolvedLookupExpr`, not only the first one. For example, we could have an 
> overload set that contains both a user-declared function and a `using` 
> declaration that names a function in `std::ranges` here.
> When found by unqualified ([basic.lookup.unqual]) name lookup for the 
> postfix-expression in a function call ([expr.call]), they inhibit 
> argument-dependent name lookup.

My interpretation of this is that both using-declarations and -directives are 
impacted (regardless of what the code says right now). [basic.lookup.unqual] 
doesn't specifically say anything about using-declarations, but I think 
[p4](https://eel.is/c++draft/basic.lookup.unqual#4) implies that they're 
included.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D129951

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


[PATCH] D129886: [clang] Add -fdiagnostics-format=sarif option for future SARIF output

2022-07-18 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added inline comments.



Comment at: clang/include/clang/Basic/DiagnosticDriverKinds.td:684
+  "diagnostic formatting in SARIF mode is currently unstable">,
+  InGroup>;
 }

abrahamcd wrote:
> Please let me know if there's a better warning group you think this should be 
> in.
Nope! This is the right way to do it :)



Comment at: clang/include/clang/Basic/DiagnosticGroups.td:1383
+
+def SarifFormatUnstable : DiagGroup<"sarif-format-unstable">;

Please make sure that there's a newline at the end of each file.



Comment at: clang/test/Driver/fdiagnostics-format-sarif.cpp:1
+// RUN: %clang -fsyntax-only -fdiagnostics-format=sarif %s

This test should check not only that we're able to use the flag, but also that 
it emits the warning.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D129886

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


[PATCH] D129886: [clang] Add -fdiagnostics-format=sarif option for future SARIF output

2022-07-19 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb accepted this revision.
cjdb added a comment.
This revision is now accepted and ready to land.

Thanks for working on this!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D129886

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


[PATCH] D129886: [clang] Add -fdiagnostics-format=sarif option for future SARIF output

2022-07-19 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added inline comments.



Comment at: clang/lib/Driver/ToolChains/Clang.cpp:4009-4011
+if (StringRef(A->getValue()) == "sarif") {
+  D.Diag(diag::warn_drv_sarif_format_unstable);
+}

aaron.ballman wrote:
> Do we want to be kind to people who spell it SARIF (given that it's an 
> acronym, some folks may spell it that way reflexively)?
tbh I think it's worth accepting both `sarif` and `SARIF`, if we can.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D129886

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


[PATCH] D129886: [clang] Add -fdiagnostics-format=sarif option for future SARIF output

2022-07-21 Thread Christopher Di Bella 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 rG119d22310bd6: [clang] Add -fdiagnostics-format=sarif option 
for future SARIF output (authored by abrahamcd, committed by cjdb).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D129886

Files:
  clang/include/clang/Basic/DiagnosticDriverKinds.td
  clang/include/clang/Basic/DiagnosticOptions.h
  clang/include/clang/Driver/Options.td
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Frontend/TextDiagnostic.cpp
  clang/test/Driver/fdiagnostics-format-sarif.cpp


Index: clang/test/Driver/fdiagnostics-format-sarif.cpp
===
--- /dev/null
+++ clang/test/Driver/fdiagnostics-format-sarif.cpp
@@ -0,0 +1,5 @@
+// RUN: %clang -fsyntax-only -fdiagnostics-format=sarif %s -### 2>&1 | 
FileCheck %s --check-prefix=WARN
+// WARN: warning: diagnostic formatting in SARIF mode is currently unstable 
[-Wsarif-format-unstable]
+
+// RUN: %clang -fsyntax-only -fdiagnostics-format=SARIF %s -### 2>&1 | 
FileCheck %s --check-prefix=WARN2
+// WARN2: warning: diagnostic formatting in SARIF mode is currently unstable 
[-Wsarif-format-unstable]
Index: clang/lib/Frontend/TextDiagnostic.cpp
===
--- clang/lib/Frontend/TextDiagnostic.cpp
+++ clang/lib/Frontend/TextDiagnostic.cpp
@@ -815,6 +815,7 @@
 
   emitFilename(PLoc.getFilename(), Loc.getManager());
   switch (DiagOpts->getFormat()) {
+  case DiagnosticOptions::SARIF:
   case DiagnosticOptions::Clang:
 if (DiagOpts->ShowLine)
   OS << ':' << LineNo;
@@ -837,6 +838,7 @@
   OS << ColNo;
 }
   switch (DiagOpts->getFormat()) {
+  case DiagnosticOptions::SARIF:
   case DiagnosticOptions::Clang:
   case DiagnosticOptions::Vi:OS << ':';break;
   case DiagnosticOptions::MSVC:
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -4007,6 +4007,9 @@
   if (const Arg *A = Args.getLastArg(options::OPT_fdiagnostics_format_EQ)) {
 CmdArgs.push_back("-fdiagnostics-format");
 CmdArgs.push_back(A->getValue());
+if (StringRef(A->getValue()) == "sarif" ||
+StringRef(A->getValue()) == "SARIF")
+  D.Diag(diag::warn_drv_sarif_format_unstable);
   }
 
   if (const Arg *A = Args.getLastArg(
Index: clang/include/clang/Driver/Options.td
===
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -5588,8 +5588,8 @@
 
 def fdiagnostics_format : Separate<["-"], "fdiagnostics-format">,
   HelpText<"Change diagnostic formatting to match IDE and command line tools">,
-  Values<"clang,msvc,vi">,
-  NormalizedValuesScope<"DiagnosticOptions">, NormalizedValues<["Clang", 
"MSVC", "Vi"]>,
+  Values<"clang,msvc,vi,sarif,SARIF">,
+  NormalizedValuesScope<"DiagnosticOptions">, NormalizedValues<["Clang", 
"MSVC", "Vi", "SARIF", "SARIF"]>,
   MarshallingInfoEnum, "Clang">;
 def fdiagnostics_show_category : Separate<["-"], "fdiagnostics-show-category">,
   HelpText<"Print diagnostic category">,
Index: clang/include/clang/Basic/DiagnosticOptions.h
===
--- clang/include/clang/Basic/DiagnosticOptions.h
+++ clang/include/clang/Basic/DiagnosticOptions.h
@@ -74,7 +74,7 @@
   friend class CompilerInvocation;
 
 public:
-  enum TextDiagnosticFormat { Clang, MSVC, Vi };
+  enum TextDiagnosticFormat { Clang, MSVC, Vi, SARIF };
 
   // Default values.
   enum {
Index: clang/include/clang/Basic/DiagnosticDriverKinds.td
===
--- clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -678,4 +678,8 @@
 def err_drv_invalid_empty_dxil_validator_version : Error<
   "invalid validator version : %0\n"
   "If validator major version is 0, minor version must also be 0.">;
+
+def warn_drv_sarif_format_unstable : Warning<
+  "diagnostic formatting in SARIF mode is currently unstable">,
+  InGroup>;
 }


Index: clang/test/Driver/fdiagnostics-format-sarif.cpp
===
--- /dev/null
+++ clang/test/Driver/fdiagnostics-format-sarif.cpp
@@ -0,0 +1,5 @@
+// RUN: %clang -fsyntax-only -fdiagnostics-format=sarif %s -### 2>&1 | FileCheck %s --check-prefix=WARN
+// WARN: warning: diagnostic formatting in SARIF mode is currently unstable [-Wsarif-format-unstable]
+
+// RUN: %clang -fsyntax-only -fdiagnostics-format=SARIF %s -### 2>&1 | FileCheck %s --check-prefix=WARN2
+// WARN2: warning: diagnostic formatting in SARIF mode is currently unstable [-Wsarif-format-unstable]
Index: clang/lib/Fr

[PATCH] D125078: Implement a feature to show line numbers in diagnostics

2022-05-09 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added subscribers: rsmith, cjdb.
cjdb added a comment.

I'm in favour of this, but @rsmith warned me a little while ago that we 
mightn't be able to have stuff like this on by default because scripts probably 
depend on specific compiler output. Hyrum's Law  
strikes again :(

(I personally think we should have it on by default and give a way to opt out, 
rather than opt in.)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D125078

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


[PATCH] D125078: Implement a feature to show line numbers in diagnostics

2022-05-10 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added a comment.

I support turning it on by default. I'm simply passing on the message.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D125078

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


[PATCH] D116203: [clang] adds unary type transformations as compiler built-ins

2022-05-13 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added inline comments.



Comment at: clang/lib/Parse/ParseDecl.cpp:4155
+#undef TRANSFORM_TYPE_TRAIT_DEF
+  if (!ParseTypeTransformTypeSpecifier(DS))
+goto ParseIdentifier;

rsmith wrote:
> The name signature you're using for this function is inconsistent with the 
> conventions in the rest of the parser: when a `Parser::Parse...` function 
> with a `bool` return type returns `true`, it means "I have failed and issued 
> a diagnostic". For "parse this if possible and return whether you did", we 
> usually use `Parser::MaybeParse...` (eg, `MaybeParseAttributes`).
> 
> Alternatively you could do the one-token lookahead here. If the `setKind` 
> call is here, it'll be a lot clearer why it makes sense to `goto 
> ParseIdentifier;`.
> 
> Also, for workarounds for a standard library issue, we normally include a `// 
> HACK:` comment explaining what we're doing and why.
Comment added, but I'd prefer to keep the function call so it keeps the logic 
self-contained and named.



Comment at: clang/lib/Sema/SemaType.cpp:9154
+  constexpr auto UKind = UTTKind::RemovePointer;
+  if (!BaseType->isPointerType() && !BaseType->isObjCObjectPointerType())
+return Context.getUnaryTransformType(BaseType, BaseType, UKind);

rsmith wrote:
> This is `!BaseType->isAnyPointerType()`.
> 
> What about block pointers? I think this patch is doing the right thing here, 
> by saying that this only applies to pointers spelled with `*` (plain and 
> obj-c pointers) and not to pointers spelled with `^`, but it seems worth 
> calling out to ensure that I'm not the only one who's thought about it :)
Done, and added a test.



Comment at: clang/lib/Sema/SemaType.cpp:9251
+  BaseType->isBooleanType()) {
+Diag(Loc, diag::err_make_signed_integral_only) << IsMakeSigned << BaseType;
+return QualType();

rsmith wrote:
> Should we support vector types here?
Is it a conforming extension for `make_signed_t` to work?



Comment at: clang/lib/Sema/SemaType.cpp:9265-9266
+  ? Context.getBitIntType(!IsMakeSigned, Context.getIntWidth(BaseType))
+  : Context.getIntTypeForBitwidth(Context.getIntWidth(BaseType),
+  IsMakeSigned);
+  Qualifiers Quals = Underlying.getQualifiers();

rsmith wrote:
> This is wrong: if, say, `int` and `long` are the same bit-width, this will 
> give the same type for `__make_unsigned(int)` and `__make_unsigned(long)`, 
> where they are required to produce `unsigned int` and `unsigned long` 
> respectively.
> 
> Please look at `Context.getCorrespondingSignedType` and 
> `Context.getCorrespondingUnsignedType` to see how to do this properly; you 
> may be able to call those functions directly in some cases, but be careful 
> about the cases where we're required to return the lowest-rank int type of 
> the given size. Note that `getIntTypeForBitwidth` does *not* do that; rather, 
> it produces the *preferred* type of the given width, and for WebAssembly and 
> AVR it produces something other than the lowest-rank type in practice in some 
> cases.
This makes me very happy.



Comment at: clang/lib/Sema/SemaType.cpp:9267-9270
+  Qualifiers Quals = Underlying.getQualifiers();
+  Quals.setCVRQualifiers(BaseType.getCVRQualifiers());
+  Underlying = QualType(Underlying.getSplitUnqualifiedType().Ty,
+Quals.getAsOpaqueValue());

rsmith wrote:
> As before, the opaque value is, well, opaque, and you shouldn't be using it 
> in this way. Also, you just created `Underlying` so you know it's 
> unqualified, so there's no need to ask for its qualifiers.
> 
> See suggested edit. Alternatively (#1), if you want to preserve all 
> qualifiers:
> 
> ```
> Underlying = Context.getQualifiedType(BaseType.getQualifiers());
> ```
> 
> Alternatively (#2) we could strictly follow the standard wording and preserve 
> only cv-qualifiers and not `restrict`. I think preserving all qualifiers is 
> more in line with the intent, but preserving only `const` and `volatile` is 
> probably the best match for what a C++ implementation of the type trait would 
> do. *shrug*
As with `decay`, I think it's best if we pretend `restrict` is a standard 
qualifier, either for everything or for nothing. However, I don't think that 
`restrict` is a valid contender here. Isn't it only applicable to pointers, 
which aren't transformed by this pair?



Comment at: clang/lib/Sema/SemaType.cpp:9136
+  Qualifiers Quals = Underlying.getQualifiers();
+  Quals.removeCVRQualifiers();
+  return Context.getUnaryTransformType(

rsmith wrote:
> cjdb wrote:
> > aaron.ballman wrote:
> > > What about things like type attributes (are those lost during decay)?
> > According to https://eel.is/c++draft/tab:meta.trans.other, no.
> Type attributes are non-standard, so we can't answer this question by looki

[PATCH] D116203: [clang] adds unary type transformations as compiler built-ins

2022-05-13 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added inline comments.



Comment at: clang/test/SemaCXX/type-traits.cpp:3495-3496
+
+  { int a[T(__is_same(make_signed_t, int))]; }
+  { int a[T(__is_same(make_signed_t, int))]; }
+  { int a[T(__is_same(make_signed_t, const int))]; }

cjdb wrote:
> rsmith wrote:
> > It'd be useful to test enums with different underlying types. However, this 
> > test is not portable: if `short` and `int` are the same size, this is 
> > required to produce `short`, not `int`. It'd be good to have some test 
> > coverage of that quirk too. Perhaps this is easiest to see with a test like:
> > 
> > ```
> > enum E : long long {};
> > static_assert(__is_same(__make_signed(E), long));
> > ```
> > 
> > ... which should hold in cases where `long` and `long long` are the same 
> > size and are larger than `int`.
> I agree, but what about when `long` is smaller than `int`?
Bleh, this is impossible. What I meant to ask is what happens when `long` and 
`int` are the same size, I think?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D116203

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


[PATCH] D116280: [clang] adds unary type trait checks as compiler built-ins

2022-05-13 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb updated this revision to Diff 429410.
cjdb added a comment.

makes `__is_destructible` and `__is_nothrow_destructible` `KEYCXX` instead of 
`KEYMS` (attention @aaron.ballman)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D116280

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/lib/Sema/SemaType.cpp
  clang/test/SemaCXX/type-traits.cpp

Index: clang/test/SemaCXX/type-traits.cpp
===
--- clang/test/SemaCXX/type-traits.cpp
+++ clang/test/SemaCXX/type-traits.cpp
@@ -345,11 +345,19 @@
 }
 
 typedef Enum EnumType;
+typedef EnumClass EnumClassType;
 
 void is_enum()
 {
   { int arr[T(__is_enum(Enum))]; }
   { int arr[T(__is_enum(EnumType))]; }
+  { int arr[T(__is_enum(SignedEnum))]; }
+  { int arr[T(__is_enum(UnsignedEnum))]; }
+
+  { int arr[T(__is_enum(EnumClass))]; }
+  { int arr[T(__is_enum(EnumClassType))]; }
+  { int arr[T(__is_enum(SignedEnumClass))]; }
+  { int arr[T(__is_enum(UnsignedEnumClass))]; }
 
   { int arr[F(__is_enum(int))]; }
   { int arr[F(__is_enum(Union))]; }
@@ -363,6 +371,29 @@
   { int arr[F(__is_enum(HasAnonymousUnion))]; }
 }
 
+void is_scoped_enum() {
+  { int arr[F(__is_scoped_enum(Enum))]; }
+  { int arr[F(__is_scoped_enum(EnumType))]; }
+  { int arr[F(__is_scoped_enum(SignedEnum))]; }
+  { int arr[F(__is_scoped_enum(UnsignedEnum))]; }
+
+  { int arr[T(__is_scoped_enum(EnumClass))]; }
+  { int arr[T(__is_scoped_enum(EnumClassType))]; }
+  { int arr[T(__is_scoped_enum(SignedEnumClass))]; }
+  { int arr[T(__is_scoped_enum(UnsignedEnumClass))]; }
+
+  { int arr[F(__is_scoped_enum(int))]; }
+  { int arr[F(__is_scoped_enum(Union))]; }
+  { int arr[F(__is_scoped_enum(Int))]; }
+  { int arr[F(__is_scoped_enum(IntAr))]; }
+  { int arr[F(__is_scoped_enum(UnionAr))]; }
+  { int arr[F(__is_scoped_enum(Derives))]; }
+  { int arr[F(__is_scoped_enum(ClassType))]; }
+  { int arr[F(__is_scoped_enum(cvoid))]; }
+  { int arr[F(__is_scoped_enum(IntArNB))]; }
+  { int arr[F(__is_scoped_enum(HasAnonymousUnion))]; }
+}
+
 struct FinalClass final {
 };
 
@@ -702,6 +733,106 @@
   int t31[F(__is_array(cvoid*))];
 }
 
+void is_bounded_array(int n) {
+  int t01[T(__is_bounded_array(IntAr))];
+  int t02[F(__is_bounded_array(IntArNB))];
+  int t03[T(__is_bounded_array(UnionAr))];
+
+  int t10[F(__is_bounded_array(void))];
+  int t11[F(__is_bounded_array(cvoid))];
+  int t12[F(__is_bounded_array(float))];
+  int t13[F(__is_bounded_array(double))];
+  int t14[F(__is_bounded_array(long double))];
+  int t15[F(__is_bounded_array(bool))];
+  int t16[F(__is_bounded_array(char))];
+  int t17[F(__is_bounded_array(signed char))];
+  int t18[F(__is_bounded_array(unsigned char))];
+  int t19[F(__is_bounded_array(wchar_t))];
+  int t20[F(__is_bounded_array(short))];
+  int t21[F(__is_bounded_array(unsigned short))];
+  int t22[F(__is_bounded_array(int))];
+  int t23[F(__is_bounded_array(unsigned int))];
+  int t24[F(__is_bounded_array(long))];
+  int t25[F(__is_bounded_array(unsigned long))];
+  int t26[F(__is_bounded_array(Union))];
+  int t27[F(__is_bounded_array(Derives))];
+  int t28[F(__is_bounded_array(ClassType))];
+  int t29[F(__is_bounded_array(Enum))];
+  int t30[F(__is_bounded_array(void *))];
+  int t31[F(__is_bounded_array(cvoid *))];
+
+  int t32[n];
+  (void)__is_bounded_array(decltype(t32)); // expected-error{{variable length arrays are not supported for '__is_bounded_array'}}
+}
+
+void is_unbounded_array(int n) {
+  int t01[F(__is_unbounded_array(IntAr))];
+  int t02[T(__is_unbounded_array(IntArNB))];
+  int t03[F(__is_unbounded_array(UnionAr))];
+
+  int t10[F(__is_unbounded_array(void))];
+  int t11[F(__is_unbounded_array(cvoid))];
+  int t12[F(__is_unbounded_array(float))];
+  int t13[F(__is_unbounded_array(double))];
+  int t14[F(__is_unbounded_array(long double))];
+  int t15[F(__is_unbounded_array(bool))];
+  int t16[F(__is_unbounded_array(char))];
+  int t17[F(__is_unbounded_array(signed char))];
+  int t18[F(__is_unbounded_array(unsigned char))];
+  int t19[F(__is_unbounded_array(wchar_t))];
+  int t20[F(__is_unbounded_array(short))];
+  int t21[F(__is_unbounded_array(unsigned short))];
+  int t22[F(__is_unbounded_array(int))];
+  int t23[F(__is_unbounded_array(unsigned int))];
+  int t24[F(__is_unbounded_array(long))];
+  int t25[F(__is_unbounded_array(unsigned long))];
+  int t26[F(__is_unbounded_array(Union))];
+  int t27[F(__is_unbounded_array(Derives))];
+  int t28[F(__is_unbounded_array(ClassType))];
+  int t29[F(__is_unbounded_array(Enum))];
+  int t30[F(__is_unbounded_array(void *))];
+  int t31[F(__is_unbounded_array(cvoid *))];
+
+  int t32[n];
+  (void)__is_unbounded_array(decltype(t32)); // expected-error{{variable length arrays are not suppor

[PATCH] D116280: [clang] adds unary type trait checks as compiler built-ins

2022-05-14 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb updated this revision to Diff 429479.
cjdb added a comment.

rebases for D116203 's sake


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D116280

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/lib/Sema/SemaType.cpp
  clang/test/SemaCXX/type-traits.cpp

Index: clang/test/SemaCXX/type-traits.cpp
===
--- clang/test/SemaCXX/type-traits.cpp
+++ clang/test/SemaCXX/type-traits.cpp
@@ -345,11 +345,19 @@
 }
 
 typedef Enum EnumType;
+typedef EnumClass EnumClassType;
 
 void is_enum()
 {
   { int arr[T(__is_enum(Enum))]; }
   { int arr[T(__is_enum(EnumType))]; }
+  { int arr[T(__is_enum(SignedEnum))]; }
+  { int arr[T(__is_enum(UnsignedEnum))]; }
+
+  { int arr[T(__is_enum(EnumClass))]; }
+  { int arr[T(__is_enum(EnumClassType))]; }
+  { int arr[T(__is_enum(SignedEnumClass))]; }
+  { int arr[T(__is_enum(UnsignedEnumClass))]; }
 
   { int arr[F(__is_enum(int))]; }
   { int arr[F(__is_enum(Union))]; }
@@ -363,6 +371,29 @@
   { int arr[F(__is_enum(HasAnonymousUnion))]; }
 }
 
+void is_scoped_enum() {
+  { int arr[F(__is_scoped_enum(Enum))]; }
+  { int arr[F(__is_scoped_enum(EnumType))]; }
+  { int arr[F(__is_scoped_enum(SignedEnum))]; }
+  { int arr[F(__is_scoped_enum(UnsignedEnum))]; }
+
+  { int arr[T(__is_scoped_enum(EnumClass))]; }
+  { int arr[T(__is_scoped_enum(EnumClassType))]; }
+  { int arr[T(__is_scoped_enum(SignedEnumClass))]; }
+  { int arr[T(__is_scoped_enum(UnsignedEnumClass))]; }
+
+  { int arr[F(__is_scoped_enum(int))]; }
+  { int arr[F(__is_scoped_enum(Union))]; }
+  { int arr[F(__is_scoped_enum(Int))]; }
+  { int arr[F(__is_scoped_enum(IntAr))]; }
+  { int arr[F(__is_scoped_enum(UnionAr))]; }
+  { int arr[F(__is_scoped_enum(Derives))]; }
+  { int arr[F(__is_scoped_enum(ClassType))]; }
+  { int arr[F(__is_scoped_enum(cvoid))]; }
+  { int arr[F(__is_scoped_enum(IntArNB))]; }
+  { int arr[F(__is_scoped_enum(HasAnonymousUnion))]; }
+}
+
 struct FinalClass final {
 };
 
@@ -702,6 +733,106 @@
   int t31[F(__is_array(cvoid*))];
 }
 
+void is_bounded_array(int n) {
+  int t01[T(__is_bounded_array(IntAr))];
+  int t02[F(__is_bounded_array(IntArNB))];
+  int t03[T(__is_bounded_array(UnionAr))];
+
+  int t10[F(__is_bounded_array(void))];
+  int t11[F(__is_bounded_array(cvoid))];
+  int t12[F(__is_bounded_array(float))];
+  int t13[F(__is_bounded_array(double))];
+  int t14[F(__is_bounded_array(long double))];
+  int t15[F(__is_bounded_array(bool))];
+  int t16[F(__is_bounded_array(char))];
+  int t17[F(__is_bounded_array(signed char))];
+  int t18[F(__is_bounded_array(unsigned char))];
+  int t19[F(__is_bounded_array(wchar_t))];
+  int t20[F(__is_bounded_array(short))];
+  int t21[F(__is_bounded_array(unsigned short))];
+  int t22[F(__is_bounded_array(int))];
+  int t23[F(__is_bounded_array(unsigned int))];
+  int t24[F(__is_bounded_array(long))];
+  int t25[F(__is_bounded_array(unsigned long))];
+  int t26[F(__is_bounded_array(Union))];
+  int t27[F(__is_bounded_array(Derives))];
+  int t28[F(__is_bounded_array(ClassType))];
+  int t29[F(__is_bounded_array(Enum))];
+  int t30[F(__is_bounded_array(void *))];
+  int t31[F(__is_bounded_array(cvoid *))];
+
+  int t32[n];
+  (void)__is_bounded_array(decltype(t32)); // expected-error{{variable length arrays are not supported for '__is_bounded_array'}}
+}
+
+void is_unbounded_array(int n) {
+  int t01[F(__is_unbounded_array(IntAr))];
+  int t02[T(__is_unbounded_array(IntArNB))];
+  int t03[F(__is_unbounded_array(UnionAr))];
+
+  int t10[F(__is_unbounded_array(void))];
+  int t11[F(__is_unbounded_array(cvoid))];
+  int t12[F(__is_unbounded_array(float))];
+  int t13[F(__is_unbounded_array(double))];
+  int t14[F(__is_unbounded_array(long double))];
+  int t15[F(__is_unbounded_array(bool))];
+  int t16[F(__is_unbounded_array(char))];
+  int t17[F(__is_unbounded_array(signed char))];
+  int t18[F(__is_unbounded_array(unsigned char))];
+  int t19[F(__is_unbounded_array(wchar_t))];
+  int t20[F(__is_unbounded_array(short))];
+  int t21[F(__is_unbounded_array(unsigned short))];
+  int t22[F(__is_unbounded_array(int))];
+  int t23[F(__is_unbounded_array(unsigned int))];
+  int t24[F(__is_unbounded_array(long))];
+  int t25[F(__is_unbounded_array(unsigned long))];
+  int t26[F(__is_unbounded_array(Union))];
+  int t27[F(__is_unbounded_array(Derives))];
+  int t28[F(__is_unbounded_array(ClassType))];
+  int t29[F(__is_unbounded_array(Enum))];
+  int t30[F(__is_unbounded_array(void *))];
+  int t31[F(__is_unbounded_array(cvoid *))];
+
+  int t32[n];
+  (void)__is_unbounded_array(decltype(t32)); // expected-error{{variable length arrays are not supported for '__is_unbounded_array'}}
+}
+
+void is_refer

[PATCH] D92176: Don't use sysroot/include when sysroot is empty.

2020-12-01 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added a comment.

In D92176#2419011 , @manojgupta wrote:

> lgtm but not an expert in this area.

Ditto


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D92176

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


[PATCH] D102728: [clang][Sema] removes -Wfree-nonheap-object reference param false positive

2021-05-18 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb created this revision.
cjdb added reviewers: gbiv, manojgupta, aaron.ballman.
Herald added a reviewer: george.burgess.iv.
Herald added subscribers: dcaballe, cota, teijeong, rdzhabarov, tatianashp, 
msifontes, jurahul, Kayjukh, grosul1, Joonsoo, liufengdb, aartbik, lucyrfox, 
mgester, arpith-jacob, antiagainst, shauheen, rriddle, mehdi_amini.
Herald added a reviewer: rriddle.
cjdb requested review of this revision.
Herald added subscribers: cfe-commits, stephenneuendorffer, nicolasvasilache.
Herald added projects: clang, MLIR.

Taking the address of a reference parameter might be valid, and without
CFA, false positives are going to be more trouble than they're worth.

This reverts commit 499571ea835daf786626a0db1e12f890b6cd8f8d 
.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D102728

Files:
  clang/lib/Sema/SemaChecking.cpp
  clang/test/Sema/warn-free-nonheap-object.cpp
  mlir/lib/IR/OperationSupport.cpp

Index: mlir/lib/IR/OperationSupport.cpp
===
--- mlir/lib/IR/OperationSupport.cpp
+++ mlir/lib/IR/OperationSupport.cpp
@@ -237,9 +237,7 @@
   if (isDynamicStorage()) {
 TrailingOperandStorage &storage = getDynamicStorage();
 storage.~TrailingOperandStorage();
-// Workaround false positive in -Wfree-nonheap-object
-auto *mem = &storage;
-free(mem);
+free(&storage);
   } else {
 getInlineStorage().~TrailingOperandStorage();
   }
@@ -373,11 +371,8 @@
 new (&newOperands[numOperands]) OpOperand(owner);
 
   // If the current storage is also dynamic, free it.
-  if (isDynamicStorage()) {
-// Workaround false positive in -Wfree-nonheap-object
-auto *mem = &storage;
-free(mem);
-  }
+  if (isDynamicStorage())
+free(&storage);
 
   // Update the storage representation to use the new dynamic storage.
   dynamicStorage.setPointerAndInt(newStorage, true);
Index: clang/test/Sema/warn-free-nonheap-object.cpp
===
--- clang/test/Sema/warn-free-nonheap-object.cpp
+++ clang/test/Sema/warn-free-nonheap-object.cpp
@@ -10,24 +10,40 @@
 
 int GI;
 
+void free_reference(char &x) { ::free(&x); }
+void free_reference(char &&x) { ::free(&x); }
+void std_free_reference(char &x) { std::free(&x); }
+void std_free_reference(char &&x) { std::free(&x); }
+
 struct S {
-  operator char *() { return ptr; }
+  operator char *() { return ptr1; }
 
   void CFree() {
-::free(&ptr); // expected-warning {{attempt to call free on non-heap object 'ptr'}}
-::free(&I);   // expected-warning {{attempt to call free on non-heap object 'I'}}
-::free(ptr);
+::free(&ptr1); // expected-warning {{attempt to call free on non-heap object 'ptr1'}}
+::free(&I);// expected-warning {{attempt to call free on non-heap object 'I'}}
+::free(ptr1);
+free_reference(*ptr2);
+free_reference(static_cast(*ptr3));
   }
 
   void CXXFree() {
-std::free(&ptr); // expected-warning {{attempt to call std::free on non-heap object 'ptr'}}
-std::free(&I);   // expected-warning {{attempt to call std::free on non-heap object 'I'}}
-std::free(ptr);
+std::free(&ptr1); // expected-warning {{attempt to call std::free on non-heap object 'ptr1'}}
+std::free(&I);// expected-warning {{attempt to call std::free on non-heap object 'I'}}
+std::free(ptr1);
+std_free_reference(*ptr2);
+std_free_reference(static_cast(*ptr3));
   }
 
 private:
-  char *ptr = (char *)std::malloc(10);
+  char *ptr1 = (char *)std::malloc(10);
+  char *ptr2 = (char *)std::malloc(10);
+  char *ptr3 = (char *)std::malloc(10);
   static int I;
+
+  static void free_reference(char &x) { ::free(&x); }
+  static void free_reference(char &&x) { ::free(&x); }
+  static void std_free_reference(char &x) { std::free(&x); }
+  static void std_free_reference(char &&x) { std::free(&x); }
 };
 
 int S::I = 0;
@@ -49,6 +65,14 @@
 int *P = &I;
 free(P);
   }
+  {
+char* P = (char *)std::malloc(2);
+free_reference(*P);
+  }
+  {
+char* P = (char *)std::malloc(2);
+free_reference(static_cast(*P));
+  }
   {
 void *P = std::malloc(8);
 free(P); // FIXME diagnosing this would require control flow analysis.
@@ -93,6 +117,14 @@
 void *P = std::malloc(8);
 std::free(P);
   }
+  {
+char* P = (char *)std::malloc(2);
+std_free_reference(*P);
+  }
+  {
+char* P = (char *)std::malloc(2);
+std_free_reference(static_cast(*P));
+  }
   {
 int A[] = {0, 1, 2, 3};
 std::free(A); // expected-warning {{attempt to call std::free on non-heap object 'A'}}
Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -10463,7 +10463,9 @@
   if (const auto *Lvalue = dyn_cast(UnaryExpr->getSubExpr())) {
 const Decl *D = Lvalue->getDecl();

[PATCH] D103380: [C++20] Support for lambdas in unevaluated context

2021-05-30 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb requested changes to this revision.
cjdb added a comment.
This revision now requires changes to proceed.

Thanks for working on this, it'll be a huge win for testing in libc++, methinks!

Could we get a few more tests please? I'd like to know what happens when we put 
a lambda directly inside:

- a SFINAE expression
- a noexcept specifier
- a sizeof operator

Similarly for lambdas inside `decltype` for each of the above. It'd also be 
good to have lambdas that aren't called as well.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D103380

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


[PATCH] D103380: [C++20] Support for lambdas in unevaluated context

2021-05-31 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb accepted this revision.
cjdb added a comment.
This revision is now accepted and ready to land.

LGTM, but I'm neither a Clang nor core expert (and I'm not a maintainer), so 
please wait for others' approval.




Comment at: clang/test/CXX/expr/expr.prim/expr.prim.lambda/p2-unevaluated.cpp:8
+
+static_assert(True);
+

Nit: please move this under line 3.



Comment at: clang/test/CXX/expr/expr.prim/expr.prim.lambda/p2-unevaluated.cpp:21
+
+Nothing<[]() { return 0; }()> nothing;
+

Nit: please move this under line 3.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D103380

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


[PATCH] D94640: adds more checks to -Wfree-nonheap-object

2021-02-08 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb updated this revision to Diff 38.
cjdb marked 4 inline comments as done.
cjdb added a comment.
Herald added a subscriber: cfe-commits.

addresses comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D94640

Files:
  clang/lib/Sema/SemaChecking.cpp
  clang/test/Analysis/free.c
  clang/test/Analysis/free.cpp
  clang/test/Analysis/weak-functions.c

Index: clang/test/Analysis/weak-functions.c
===
--- clang/test/Analysis/weak-functions.c
+++ clang/test/Analysis/weak-functions.c
@@ -71,7 +71,9 @@
 void free(void *) __attribute__((weak_import));
 
 void t10 () {
-  free((void*)&t10); // expected-warning {{Argument to free() is the address of the function 't10', which is not memory allocated by malloc()}}
+  free((void*)&t10);
+  // expected-warning@-1{{Argument to free() is the address of the function 't10', which is not memory allocated by malloc()}}
+  // expected-warning@-2{{attempt to call free on non-heap object 't10'}}
 }
 
 //===--===
Index: clang/test/Analysis/free.cpp
===
--- /dev/null
+++ clang/test/Analysis/free.cpp
@@ -0,0 +1,210 @@
+// RUN: %clang_analyze_cc1 -fblocks -verify %s -analyzer-store=region \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=unix.Malloc
+//
+// RUN: %clang_analyze_cc1 -fblocks -verify %s -analyzer-store=region \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=unix.Malloc \
+// RUN:   -analyzer-config unix.DynamicMemoryModeling:Optimistic=true
+namespace std {
+  using size_t = decltype(sizeof(int));
+  void free(void *);
+}
+
+extern "C" void free(void *);
+extern "C" void *alloca(std::size_t);
+
+void t1a () {
+  int a[] = { 1 };
+  free(a);
+  // expected-warning@-1{{Argument to free() is the address of the local variable 'a', which is not memory allocated by malloc()}}
+  // expected-warning@-2{{attempt to call free on non-heap object 'a'}}
+}
+
+void t1b () {
+  int a[] = { 1 };
+  std::free(a);
+  // expected-warning@-1{{Argument to free() is the address of the local variable 'a', which is not memory allocated by malloc()}}
+  // expected-warning@-2{{attempt to call std::free on non-heap object 'a'}}
+}
+
+void t2a () {
+  int a = 1;
+  free(&a);
+  // expected-warning@-1{{Argument to free() is the address of the local variable 'a', which is not memory allocated by malloc()}}
+  // expected-warning@-2{{attempt to call free on non-heap object 'a'}}
+}
+
+void t2b () {
+  int a = 1;
+  std::free(&a);
+  // expected-warning@-1{{Argument to free() is the address of the local variable 'a', which is not memory allocated by malloc()}}
+  // expected-warning@-2{{attempt to call std::free on non-heap object 'a'}}
+}
+
+void t3a () {
+  static int a[] = { 1 };
+  free(a);
+  // expected-warning@-1{{Argument to free() is the address of the static variable 'a', which is not memory allocated by malloc()}}
+  // expected-warning@-2{{attempt to call free on non-heap object 'a'}}
+}
+
+void t3b () {
+  static int a[] = { 1 };
+  std::free(a);
+  // expected-warning@-1{{Argument to free() is the address of the static variable 'a', which is not memory allocated by malloc()}}
+  // expected-warning@-2{{attempt to call std::free on non-heap object 'a'}}
+}
+
+void t4a (char *x) {
+  free(x); // no-warning
+}
+
+void t4b (char *x) {
+  std::free(x); // no-warning
+}
+
+void t5a () {
+  extern char *ptr();
+  free(ptr()); // no-warning
+}
+
+void t5b () {
+  extern char *ptr();
+  std::free(ptr()); // no-warning
+}
+
+void t6a () {
+  free((void*)1000);
+  // expected-warning@-1{{Argument to free() is a constant address (1000), which is not memory allocated by malloc()}}
+  // expected-warning@-2{{attempt to call free on non-heap object '(void *)1000'}}
+}
+
+void t6b () {
+  std::free((void*)1000);
+  // expected-warning@-1{{Argument to free() is a constant address (1000), which is not memory allocated by malloc()}}
+  // expected-warning@-2{{attempt to call std::free on non-heap object '(void *)1000'}}
+}
+
+void t7a (char **x) {
+  free(*x); // no-warning
+}
+
+void t7b (char **x) {
+  std::free(*x); // no-warning
+}
+
+void t8a (char **x) {
+  // ugh
+  free((*x)+8); // no-warning
+}
+
+void t8b (char **x) {
+  // ugh
+  std::free((*x)+8); // no-warning
+}
+
+void t9a () {
+label:
+  free(&&label);
+  // expected-warning@-1{{Argument to free() is the address of the label 'label', which is not memory allocated by malloc()}}
+  // expected-warning@-2{{attempt to call free on non-heap object 'label'}}
+}
+
+void t9b () {
+label:
+  std::free(&&label);
+  // expected-warning@-1{{Argument to free() is the address of the label 'label', which is not memory allocated by malloc()}}
+  // expected-warning@-2{{attempt to call std::free on non-heap object 'label'}}
+}
+
+void t1

[PATCH] D94640: adds more checks to -Wfree-nonheap-object

2021-02-08 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added inline comments.



Comment at: clang/lib/Sema/SemaChecking.cpp:10267-10277
+  if (const auto *Field = dyn_cast(D)) {
 S.Diag(UnaryExpr->getBeginLoc(), diag::warn_free_nonheap_object)
 << CalleeName << Field;
+return;
+  }
+
+  if (const auto *Func = dyn_cast(D)) {

aaron.ballman wrote:
> I think this simplifies things a bit (even though it's doing an `isa<>` 
> followed by a `cast<>`).
Wow, that's much nicer, thanks! :D



Comment at: clang/lib/Sema/SemaChecking.cpp:10286-10289
 if (const auto *Var = dyn_cast(Lvalue->getDecl()))
   return CheckFreeArgumentsOnLvalue(S, CalleeName, UnaryExpr, Var);
+if (const auto *Var = dyn_cast(Lvalue->getDecl()))
+  return CheckFreeArgumentsOnLvalue(S, CalleeName, UnaryExpr, Var);

aaron.ballman wrote:
> 
This one required a bit more work than the previous one because there are two 
overloads for `CheckFreeArgumentsOnLvalue`.



Comment at: clang/lib/Sema/SemaChecking.cpp:10312
+const CastExpr *Cast) {
+  auto const kind = Cast->getCastKind();
+  switch (kind) {

aaron.ballman wrote:
> Please spell out the type (also, we don't typically use top-level `const` 
> qualification on local variables or parameters).
Heh, this was only named for debugging purposes. I've consolidated it into the 
switch statement ;-)



Comment at: clang/lib/Sema/SemaChecking.cpp:10314
+  switch (kind) {
+  case clang::CK_IntegralToPointer: // [[fallthrough]];
+  case clang::CK_FunctionToPointerDecay: {

aaron.ballman wrote:
> 
Done, but why? I quite like making it clear that fallthrough is intentional.



Comment at: clang/lib/Sema/SemaChecking.cpp:10337
+  // Prefer something that doesn't involve a cast to make things simpler.
+  {
+const Expr *Arg = E->getArg(0)->IgnoreParenCasts();

aaron.ballman wrote:
> The extra compound scope doesn't add too much, so I'd remove it.
I find it improves readability and groups what the comment above it (now inline 
with `{`) is talking about.



Comment at: clang/lib/Sema/SemaChecking.cpp:10351
+
+if (const auto *Block = dyn_cast(Arg)) {
+  Diag(Block->getBeginLoc(), diag::warn_free_nonheap_object)

aaron.ballman wrote:
> Any reason not to handle `LambdaExpr` at the same time?
None, I hadn't considered it. I'm not sure I see the relationship bet



Comment at: clang/test/Analysis/free.c:84
+  // expected-warning@-1{{Argument to free() is a block, which is not memory 
allocated by malloc()}}
+  // expected-warning@-2{{attempt to call free on non-heap object : block 
expression}}
 }

aaron.ballman wrote:
> The formatting for this diagnostic is somewhat unfortunate in that it has the 
> leading space before the `:`. I think that changing the diagnostic to use a 
> `%select` would be an improvement.
I'm having a *lot* of difficulty getting `%select` to work. Here's what I've 
tried, but the space in `%select{ %2` is being ignored :(

```
: Warning<"attempt to call %0 on non-heap object%select{ %2|: block 
expression}1">,
```


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D94640

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


[PATCH] D94640: adds more checks to -Wfree-nonheap-object

2021-02-11 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb added inline comments.



Comment at: clang/test/Analysis/free.c:84
+  // expected-warning@-1{{Argument to free() is a block, which is not memory 
allocated by malloc()}}
+  // expected-warning@-2{{attempt to call free on non-heap object : block 
expression}}
 }

aaron.ballman wrote:
> cjdb wrote:
> > aaron.ballman wrote:
> > > The formatting for this diagnostic is somewhat unfortunate in that it has 
> > > the leading space before the `:`. I think that changing the diagnostic to 
> > > use a `%select` would be an improvement.
> > I'm having a *lot* of difficulty getting `%select` to work. Here's what 
> > I've tried, but the space in `%select{ %2` is being ignored :(
> > 
> > ```
> > : Warning<"attempt to call %0 on non-heap object%select{ %2|: block 
> > expression}1">,
> > ```
> We could cheat a little bit. :-D
> 
> `Warning<"attempt to call %0 on non-heap %select{object %2|object: block 
> expression}1">`
> 
> (The diagnostic should probably be updated to distinguish between block 
> expressions and lambda expressions, which may add another layer of `%select` 
> not shown here.)
That doesn't fix the issue, which is that everything before `%2` is deleted.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D94640

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


[PATCH] D94640: adds more checks to -Wfree-nonheap-object

2021-02-12 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb updated this revision to Diff 323414.
cjdb added a comment.

fixes block expressions

@aaron.ballman I'm not sure I follow what you're after re lambdas. Could you 
please provide a test case that I can work with?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D94640

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaChecking.cpp
  clang/test/Analysis/free.c
  clang/test/Analysis/free.cpp
  clang/test/Analysis/weak-functions.c

Index: clang/test/Analysis/weak-functions.c
===
--- clang/test/Analysis/weak-functions.c
+++ clang/test/Analysis/weak-functions.c
@@ -71,7 +71,9 @@
 void free(void *) __attribute__((weak_import));
 
 void t10 () {
-  free((void*)&t10); // expected-warning {{Argument to free() is the address of the function 't10', which is not memory allocated by malloc()}}
+  free((void*)&t10);
+  // expected-warning@-1{{Argument to free() is the address of the function 't10', which is not memory allocated by malloc()}}
+  // expected-warning@-2{{attempt to call free on non-heap object 't10'}}
 }
 
 //===--===
Index: clang/test/Analysis/free.cpp
===
--- /dev/null
+++ clang/test/Analysis/free.cpp
@@ -0,0 +1,210 @@
+// RUN: %clang_analyze_cc1 -fblocks -verify %s -analyzer-store=region \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=unix.Malloc
+//
+// RUN: %clang_analyze_cc1 -fblocks -verify %s -analyzer-store=region \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=unix.Malloc \
+// RUN:   -analyzer-config unix.DynamicMemoryModeling:Optimistic=true
+namespace std {
+  using size_t = decltype(sizeof(int));
+  void free(void *);
+}
+
+extern "C" void free(void *);
+extern "C" void *alloca(std::size_t);
+
+void t1a () {
+  int a[] = { 1 };
+  free(a);
+  // expected-warning@-1{{Argument to free() is the address of the local variable 'a', which is not memory allocated by malloc()}}
+  // expected-warning@-2{{attempt to call free on non-heap object 'a'}}
+}
+
+void t1b () {
+  int a[] = { 1 };
+  std::free(a);
+  // expected-warning@-1{{Argument to free() is the address of the local variable 'a', which is not memory allocated by malloc()}}
+  // expected-warning@-2{{attempt to call std::free on non-heap object 'a'}}
+}
+
+void t2a () {
+  int a = 1;
+  free(&a);
+  // expected-warning@-1{{Argument to free() is the address of the local variable 'a', which is not memory allocated by malloc()}}
+  // expected-warning@-2{{attempt to call free on non-heap object 'a'}}
+}
+
+void t2b () {
+  int a = 1;
+  std::free(&a);
+  // expected-warning@-1{{Argument to free() is the address of the local variable 'a', which is not memory allocated by malloc()}}
+  // expected-warning@-2{{attempt to call std::free on non-heap object 'a'}}
+}
+
+void t3a () {
+  static int a[] = { 1 };
+  free(a);
+  // expected-warning@-1{{Argument to free() is the address of the static variable 'a', which is not memory allocated by malloc()}}
+  // expected-warning@-2{{attempt to call free on non-heap object 'a'}}
+}
+
+void t3b () {
+  static int a[] = { 1 };
+  std::free(a);
+  // expected-warning@-1{{Argument to free() is the address of the static variable 'a', which is not memory allocated by malloc()}}
+  // expected-warning@-2{{attempt to call std::free on non-heap object 'a'}}
+}
+
+void t4a (char *x) {
+  free(x); // no-warning
+}
+
+void t4b (char *x) {
+  std::free(x); // no-warning
+}
+
+void t5a () {
+  extern char *ptr();
+  free(ptr()); // no-warning
+}
+
+void t5b () {
+  extern char *ptr();
+  std::free(ptr()); // no-warning
+}
+
+void t6a () {
+  free((void*)1000);
+  // expected-warning@-1{{Argument to free() is a constant address (1000), which is not memory allocated by malloc()}}
+  // expected-warning@-2{{attempt to call free on non-heap object '(void *)1000'}}
+}
+
+void t6b () {
+  std::free((void*)1000);
+  // expected-warning@-1{{Argument to free() is a constant address (1000), which is not memory allocated by malloc()}}
+  // expected-warning@-2{{attempt to call std::free on non-heap object '(void *)1000'}}
+}
+
+void t7a (char **x) {
+  free(*x); // no-warning
+}
+
+void t7b (char **x) {
+  std::free(*x); // no-warning
+}
+
+void t8a (char **x) {
+  // ugh
+  free((*x)+8); // no-warning
+}
+
+void t8b (char **x) {
+  // ugh
+  std::free((*x)+8); // no-warning
+}
+
+void t9a () {
+label:
+  free(&&label);
+  // expected-warning@-1{{Argument to free() is the address of the label 'label', which is not memory allocated by malloc()}}
+  // expected-warning@-2{{attempt to call free on non-heap object 'label'}}
+}
+
+void t9b () {
+label:
+  std::free(&&label);
+  // expected-warning@-1{{Argument to free() is the address of the label 'label', which is not memory allocated by m

[PATCH] D94640: adds more checks to -Wfree-nonheap-object

2021-02-12 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb marked 3 inline comments as done.
cjdb added inline comments.



Comment at: clang/test/Analysis/free.c:84
+  // expected-warning@-1{{Argument to free() is a block, which is not memory 
allocated by malloc()}}
+  // expected-warning@-2{{attempt to call free on non-heap object : block 
expression}}
 }

aaron.ballman wrote:
> cjdb wrote:
> > aaron.ballman wrote:
> > > cjdb wrote:
> > > > aaron.ballman wrote:
> > > > > The formatting for this diagnostic is somewhat unfortunate in that it 
> > > > > has the leading space before the `:`. I think that changing the 
> > > > > diagnostic to use a `%select` would be an improvement.
> > > > I'm having a *lot* of difficulty getting `%select` to work. Here's what 
> > > > I've tried, but the space in `%select{ %2` is being ignored :(
> > > > 
> > > > ```
> > > > : Warning<"attempt to call %0 on non-heap object%select{ %2|: block 
> > > > expression}1">,
> > > > ```
> > > We could cheat a little bit. :-D
> > > 
> > > `Warning<"attempt to call %0 on non-heap %select{object %2|object: block 
> > > expression}1">`
> > > 
> > > (The diagnostic should probably be updated to distinguish between block 
> > > expressions and lambda expressions, which may add another layer of 
> > > `%select` not shown here.)
> > That doesn't fix the issue, which is that everything before `%2` is deleted.
> Huh? That seems very surprising given that we use this pattern in plenty of 
> other places:
> 
> https://github.com/llvm/llvm-project/blob/main/clang/include/clang/Basic/DiagnosticSemaKinds.td#L483
> https://github.com/llvm/llvm-project/blob/main/clang/include/clang/Basic/DiagnosticSemaKinds.td#L685
> https://github.com/llvm/llvm-project/blob/main/clang/include/clang/Basic/DiagnosticSemaKinds.td#L1439
> 
> Can you post the output you're getting when you try my workaround? (I don't 
> know if your original attempt will work because of the lack of whitespace 
> before the `%select` in `object%select`.)
Yeah, not sure what was going on here (maybe I didn't hit save before 
testing?), since it ICEd up when I re-applied it. Anyway, got it working :-)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D94640

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


[PATCH] D94640: adds more checks to -Wfree-nonheap-object

2021-02-22 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb marked an inline comment as done.
cjdb added a comment.

Ping. @aaron.ballman any further requests? I think this is good to land 
otherwise?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D94640

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


[PATCH] D94640: adds more checks to -Wfree-nonheap-object

2021-02-23 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb marked an inline comment as done.
cjdb added a comment.

In D94640#2579447 , @aaron.ballman 
wrote:

> In D94640#2560647 , @cjdb wrote:
>
>> fixes block expressions
>>
>> @aaron.ballman I'm not sure I follow what you're after re lambdas. Could you 
>> please provide a test case that I can work with?
>
> Sorry about missing your question -- this fell off my radar. I was thinking 
> it'd be roughly the same as blocks, but I now think this'll create compile 
> errors anyway: `free([]{ return nullptr; });` (where the lambda is 
> accidentally not being called). So not nearly as important as I was thinking 
> (sorry for that, but thank you for adding the support and test cases just the 
> same!).
>
> One worry I have is the number of effectively duplicated diagnostics we're 
> now getting in conjunction with the static analyzer. It's not quite perfect 
> overlap and so we can't get rid of the static analyzer check, but is there a 
> long-term plan for how to resolve this?

I filed issue 48767 , but I don't 
think the analyser folks are motivated to address it any time soon.




Comment at: clang/lib/Sema/SemaChecking.cpp:10252
 namespace {
-void CheckFreeArgumentsOnLvalue(Sema &S, const std::string &CalleeName,
-const UnaryOperator *UnaryExpr,
-const VarDecl *Var) {
-  StorageClass Class = Var->getStorageClass();
-  if (Class == StorageClass::SC_Extern ||
-  Class == StorageClass::SC_PrivateExtern ||
-  Var->getType()->isReferenceType())
-return;
-
-  S.Diag(UnaryExpr->getBeginLoc(), diag::warn_free_nonheap_object)
-  << CalleeName << Var;
-}
+constexpr int Placeholder = 0;
 

aaron.ballman wrote:
> After seeing my suggested workaround in practice, I'm hopeful we can figure 
> out how to get the diagnostics engine to not require us to jump through these 
> hoops. I wouldn't block the patch over this approach, but it's not very 
> obvious what's happening from reading the code either.
Sorry, I'm not entirely sure what you're getting at here? :/



Comment at: clang/lib/Sema/SemaChecking.cpp:10342
+  static constexpr int NoPlaceholder = 1;
+  Diag(Arg->getBeginLoc(), diag::warn_free_nonheap_object)
+  << CalleeName << NoPlaceholder;

aaron.ballman wrote:
> FWIW, this diagnostic will be awkward for lambdas because it mentions blocks 
> explicitly. It's not critical thing given how hard it would be to hit the 
> lambda case, but if you think of an easy way to solve it, I won't complain.
Nothing "easy" comes to mind.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D94640

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


[PATCH] D94640: adds more checks to -Wfree-nonheap-object

2021-02-23 Thread Christopher Di Bella via Phabricator via cfe-commits
cjdb updated this revision to Diff 325889.
cjdb added a comment.

applies @aaron.ballman's feedback


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D94640

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaChecking.cpp
  clang/test/Analysis/free.c
  clang/test/Analysis/free.cpp
  clang/test/Analysis/malloc-fnptr-plist.c
  clang/test/Analysis/malloc.c
  clang/test/Analysis/weak-functions.c

Index: clang/test/Analysis/weak-functions.c
===
--- clang/test/Analysis/weak-functions.c
+++ clang/test/Analysis/weak-functions.c
@@ -71,7 +71,9 @@
 void free(void *) __attribute__((weak_import));
 
 void t10 () {
-  free((void*)&t10); // expected-warning {{Argument to free() is the address of the function 't10', which is not memory allocated by malloc()}}
+  free((void*)&t10);
+  // expected-warning@-1{{Argument to free() is the address of the function 't10', which is not memory allocated by malloc()}}
+  // expected-warning@-2{{attempt to call free on non-heap object 't10'}}
 }
 
 //===--===
Index: clang/test/Analysis/malloc.c
===
--- clang/test/Analysis/malloc.c
+++ clang/test/Analysis/malloc.c
@@ -1780,7 +1780,9 @@
 }
 
 void freeFunctionPtr() {
-  free((void *)fnptr); // expected-warning {{Argument to free() is a function pointer}}
+  free((void *)fnptr);
+  // expected-warning@-1{{Argument to free() is a function pointer}}
+  // expected-warning@-2{{attempt to call free on non-heap object '(void *)fnptr'}}
 }
 
 void allocateSomeMemory(void *offendingParameter, void **ptr) {
Index: clang/test/Analysis/malloc-fnptr-plist.c
===
--- clang/test/Analysis/malloc-fnptr-plist.c
+++ clang/test/Analysis/malloc-fnptr-plist.c
@@ -4,7 +4,9 @@
 void free(void *);
 void (*fnptr)(int);
 void foo() {
-  free((void *)fnptr); // expected-warning{{Argument to free() is a function pointer}}
+  free((void *)fnptr);
+  // expected-warning@-1{{Argument to free() is a function pointer}}
+  // expected-warning@-2{{attempt to call free on non-heap object '(void *)fnptr'}}
 }
 
 // Make sure the bug category is correct.
Index: clang/test/Analysis/free.cpp
===
--- /dev/null
+++ clang/test/Analysis/free.cpp
@@ -0,0 +1,210 @@
+// RUN: %clang_analyze_cc1 -fblocks -verify %s -analyzer-store=region \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=unix.Malloc
+//
+// RUN: %clang_analyze_cc1 -fblocks -verify %s -analyzer-store=region \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=unix.Malloc \
+// RUN:   -analyzer-config unix.DynamicMemoryModeling:Optimistic=true
+namespace std {
+  using size_t = decltype(sizeof(int));
+  void free(void *);
+}
+
+extern "C" void free(void *);
+extern "C" void *alloca(std::size_t);
+
+void t1a () {
+  int a[] = { 1 };
+  free(a);
+  // expected-warning@-1{{Argument to free() is the address of the local variable 'a', which is not memory allocated by malloc()}}
+  // expected-warning@-2{{attempt to call free on non-heap object 'a'}}
+}
+
+void t1b () {
+  int a[] = { 1 };
+  std::free(a);
+  // expected-warning@-1{{Argument to free() is the address of the local variable 'a', which is not memory allocated by malloc()}}
+  // expected-warning@-2{{attempt to call std::free on non-heap object 'a'}}
+}
+
+void t2a () {
+  int a = 1;
+  free(&a);
+  // expected-warning@-1{{Argument to free() is the address of the local variable 'a', which is not memory allocated by malloc()}}
+  // expected-warning@-2{{attempt to call free on non-heap object 'a'}}
+}
+
+void t2b () {
+  int a = 1;
+  std::free(&a);
+  // expected-warning@-1{{Argument to free() is the address of the local variable 'a', which is not memory allocated by malloc()}}
+  // expected-warning@-2{{attempt to call std::free on non-heap object 'a'}}
+}
+
+void t3a () {
+  static int a[] = { 1 };
+  free(a);
+  // expected-warning@-1{{Argument to free() is the address of the static variable 'a', which is not memory allocated by malloc()}}
+  // expected-warning@-2{{attempt to call free on non-heap object 'a'}}
+}
+
+void t3b () {
+  static int a[] = { 1 };
+  std::free(a);
+  // expected-warning@-1{{Argument to free() is the address of the static variable 'a', which is not memory allocated by malloc()}}
+  // expected-warning@-2{{attempt to call std::free on non-heap object 'a'}}
+}
+
+void t4a (char *x) {
+  free(x); // no-warning
+}
+
+void t4b (char *x) {
+  std::free(x); // no-warning
+}
+
+void t5a () {
+  extern char *ptr();
+  free(ptr()); // no-warning
+}
+
+void t5b () {
+  extern char *ptr();
+  std::free(ptr()); // no-warning
+}
+
+void t6a () {
+  free((void*)1000);
+  // expected-warning@-1{{

  1   2   3   4   5   >