[PATCH] D134475: Add C++11 attribute msvc::constexpr

2023-03-26 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added a comment.

I am sorry for protracting implementation. I am still interested to finish this 
(if no volunteer takes over sooner).

In D134475#4070995 , @RIscRIpt wrote:

> I asked MSFT 
> 
>  to comment, let's see if they can share the spec for this attribute.

They did answer! Thank you Cody! For sake of backup, I'll re-post Cody Miller's 
comment here

> In Microsoft Developer Community / msvc::constexpr-specification 
> ,
>  **Cody Miller** wrote:
> Hello!
>
> We added `[[msvc::constexpr]]` to support `std::construct_at` and 
> `std::ranges::construct_at`. These functions are used in lieu of placement 
> new in constexpr contexts to support the forms of dynamic memory allocation 
> that C++20 supports.
>
> We originally implemented this by intercepting the names of the invoked 
> functions and implemented them within the compiler. We (the compiler team) 
> ultimately weren’t satisfied with this approach because it added complexity 
> to the frontend and led to some surprising behavior (such as users 
> implementing their own `std::construct_at` (technically invoking 
> undefined-behavior, I think) and seeing behavior that may have differed from 
> their implementation).
>
> We added the attribute to allow limited contexts to invoke placement new 
> during constexpr evaluation, which allowed the compiler to handle the 
> standard library’s implementation of the two special functions mentioned 
> above.
>
> The semantics are (from memory on a Sunday evening, apologies for unclear or 
> forgotten explanations):
>
> - A function may be either `[[msvc::constexpr]]`, `constexpr`, or neither, 
> but no combination of these is allowed.
> - A function annotated with `[[msvc::constexpr]]` is unofficially called an 
> “extended constexpr” function and may call other `constexpr` or extended 
> constexpr functions.
> - An extended constexpr function has the same restrictions as a constexpr 
> function, except when otherwise noted here.
> - A return statement may be annotated with `[[msvc::constexpr]]` to allow its 
> containing constexpr function to call an extended constexpr function.
> - An extended constexpr function can call other extended constexpr functions 
> without a statement-level annotation.
> - A constexpr function may use placement new within a return statement 
> annotated with `[[msvc::constexpr]]`.
>
> We aimed to add a general mechanism to support this feature, but we only are 
> officially supporting it for use in `std::construct_at` and 
> `std::ranges::construct_at` at the moment – feel free to file bugs if you 
> find issues through experimentation, though!
>
> The restriction to the `return` statement is reflective of us wanting to keep 
> the scope of the attribute small.
>
> Here’s a godbolt link that hopefully clearly captures the above.
>
> We use the annotation (behind the `_MSVC_CONSTEXPR` macro) in our STL 
> implementation in two 
> 
>  places 
> .
>
> Hope this explanation helps! Let me know if anything is unclear.

Currently I am lingered to decide how to implement checks for constant 
evaluation in clang/lib/AST/ExprConstant.cpp 
.
At the moment I have two ideas:
Idea 1: Using helper RAII classes like `BlockScopeRAII` keep track of 
`AttributedStmt` and `ReturnStmt` in `EvalInfo` and/or `CallStackFrame`; then 
in CheckConstexprFunction 

 check whether above rules are followed. However I don't see that `EvalInfo` or 
`CallStackFrame` allow storing references to arbitrary statements, and 
extending these classes only to support `[[msvc::constexpr]]` does not sound 
like a reasonable idea.
Idea 2: Pass `Expr* CallerExpr` to CheckConstexprFunction 
,
 and then traverse parents of `CallerExpr` to check that above rules are 
followed. This would require implementing a simple `ParentVisitor` class which 
would use `ParentMapContext`. I'm not completely sure about this idea, because 
I see that `ParentMapContext` is used seldom and its docs mention about 
"opportunities for optimization" (sounds like performance problems).

By the way, it feels weird that we have to implement complex checks (for 
attributed return statement) only to limit the possibilities of constant 
evaluation; on the other hand without these chec

[PATCH] D148926: [Clang] Add support for [[msvc::constexpr]] C++11 attribute

2023-04-21 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt created this revision.
Herald added a reviewer: aaron.ballman.
Herald added a subscriber: jdoerfert.
Herald added a project: All.
RIscRIpt requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D148926

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/include/clang/Basic/DiagnosticASTKinds.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/AST/ExprConstant.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaStmtAttr.cpp
  clang/test/AST/msvc-attrs-invalid.cpp
  clang/test/AST/msvc-attrs.cpp
  clang/test/AST/msvc-constexpr-new.cpp
  clang/test/Misc/pragma-attribute-supported-attributes-list.test

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
@@ -83,6 +83,7 @@
 // CHECK-NEXT: LoaderUninitialized (SubjectMatchRule_variable_is_global)
 // CHECK-NEXT: Lockable (SubjectMatchRule_record)
 // CHECK-NEXT: MIGServerRoutine (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_block)
+// CHECK-NEXT: MSConstexpr (SubjectMatchRule_function)
 // CHECK-NEXT: MSStruct (SubjectMatchRule_record)
 // CHECK-NEXT: MaybeUndef (SubjectMatchRule_variable_is_parameter)
 // CHECK-NEXT: MicroMips (SubjectMatchRule_function)
Index: clang/test/AST/msvc-constexpr-new.cpp
===
--- /dev/null
+++ clang/test/AST/msvc-constexpr-new.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fms-extensions -std=c++20 -ast-dump %s | FileCheck %s
+
+// CHECK: used operator new
+// CHECK: MSConstexprAttr 0x{{[0-9a-f]+}} 
+[[nodiscard]] [[msvc::constexpr]] inline void* __cdecl operator new(decltype(sizeof(void*)), void* p) noexcept { return p; }
+
+// CHECK: used constexpr construct_at
+// CHECK: AttributedStmt 0x{{[0-9a-f]+}} 
+// CHECK-NEXT: MSConstexprAttr 0x{{[0-9a-f]+}} 
+// CHECK-NEXT: ReturnStmt 0x{{[0-9a-f]+}} 
+constexpr int* construct_at(int* p, int v) { [[msvc::constexpr]] return ::new (p) int(v); }
+
+constexpr bool check_construct_at() { int x; return *construct_at(&x, 42) == 42; }
+
+static_assert(check_construct_at());
Index: clang/test/AST/msvc-attrs.cpp
===
--- /dev/null
+++ clang/test/AST/msvc-attrs.cpp
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -fms-extensions -std=c++20 -ast-dump %s | FileCheck %s
+
+// [[msvc::constexpr]] tests
+
+// MSConstexprDocs (1)
+// CHECK: used f1 'bool ()'
+// CHECK: MSConstexprAttr 0x{{[0-9a-f]+}} 
+[[msvc::constexpr]] bool f1() { return true; }
+
+// MSConstexprDocs (2)
+// CHECK: used constexpr f2 'bool ()'
+// CHECK: AttributedStmt 0x{{[0-9a-f]+}} 
+// CHECK-NEXT: MSConstexprAttr 0x{{[0-9a-f]+}} 
+// CHECK-NEXT: ReturnStmt 0x{{[0-9a-f]+}} 
+constexpr bool f2() { [[msvc::constexpr]] return f1(); }
+
+static_assert(f2());
+
+constexpr bool f3() { [[msvc::constexpr]] return f1() || f1() && f1(); }
+static_assert(f3());
+
+[[msvc::constexpr]] int f4(int x) { [[msvc::constexpr]] return x > 1 ? 1 + f4(x / 2) : 0; }
+constexpr bool f5() { [[msvc::constexpr]] return f4(32) == 5; }
+static_assert(f5());
+
+[[msvc::constexpr]] int f6(int x)
+{
+switch (x)
+{
+case 42: return 1337;
+default:
+ if (x < 0) [[msvc::constexpr]] return f4(-x);
+ else return x;
+}
+}
+
+constexpr bool f7() { [[msvc::constexpr]] return f6(f6(42) - 1337 + f6(-32) - 5 + (f6(1) ? f6(0) : f6(2))) == f6(0); }
+static_assert(f7());
Index: clang/test/AST/msvc-attrs-invalid.cpp
===
--- /dev/null
+++ clang/test/AST/msvc-attrs-invalid.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -fms-extensions -std=c++20 -verify %s
+
+// Check explicitly invalid code
+
+void runtime() {} // expected-note {{declared here}}
+
+[[msvc::constexpr]] void f0() { runtime(); } // expected-error {{[[msvc::constexpr]] function never produces a constant expression}} \
+ // expected-note {{non-constexpr function 'runtime' cannot be used in a constant expression}}
+[[msvc::constexpr]] constexpr void f1() {} // expected-error {{[[msvc::constexpr]] cannot be applied to a constexpr function 'f1'}}
+[[msvc::constexpr]] consteval void f2() {} // expected-error {{[[msvc::constexpr]] cannot be applied to a consteval function 'f2'}}
+
+// Check invalid code mixed with valid code
+
+[[msvc::constexpr]] bool undefined();
+
+[[msvc::constexpr]] int f4(int x) { return x > 1 ? 1 + f4(x / 2) : 0; } // expected-note {{[[msvc::constexpr]] function 'f4' is used not in '[[msvc::constexpr]] return' statement}}
+constexpr bool f5() {

[PATCH] D148926: [Clang] Add support for [[msvc::constexpr]] C++11 attribute

2023-04-21 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt abandoned this revision.
RIscRIpt added a comment.

This had to be submitted to https://reviews.llvm.org/D134475


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D148926

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


[PATCH] D134475: Add C++11 attribute msvc::constexpr

2023-04-21 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 515740.
RIscRIpt added a comment.

A proper implementation

In D134475#4224082 , @erichkeane 
wrote:

> I don't have a good idea, I don't think any sort of RAII object is the right 
> way (since it will be wrong on child calls/etc), and the ParentMap is 
> definitely not the right way.  Perhaps just a flag for 
> CheckConstexprFunction?  I've not spent too much time in this section of the 
> compiler, so hopefully someone else can come along and help. I suspect it is 
> a property of `CallStackFrame`?  But that already contains a link to the 
> FucntionDecl, right?  As far as the 'on return statement', I think the bit on 
> CallStackFrame/EvalInfo is probably what is necessary.



> But that already contains a link to the FucntionDecl, right?

Yes, but we need to know current context (whether we're in `[[msvc::constexpr]] 
return` statement).

> As far as the 'on return statement', I think the bit on 
> CallStackFrame/EvalInfo is probably what is necessary.

That's what I ended-up doing. This was the most reasonable approach I could 
come-up with.

I added a property to `CallStackFrame`, because it's a property of current 
function: whether we are in valid context which permits evaluation of 
`[[msvc::constexpr]]`. Additionally I added `MSConstexprContextRAII` which is 
used in `case Stmt::AttributedStmtClass:` to alter the property.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134475

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/include/clang/Basic/DiagnosticASTKinds.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/AST/ExprConstant.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaStmtAttr.cpp
  clang/test/AST/msvc-attrs-invalid.cpp
  clang/test/AST/msvc-attrs.cpp
  clang/test/AST/msvc-constexpr-new.cpp
  clang/test/Misc/pragma-attribute-supported-attributes-list.test

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
@@ -83,6 +83,7 @@
 // CHECK-NEXT: LoaderUninitialized (SubjectMatchRule_variable_is_global)
 // CHECK-NEXT: Lockable (SubjectMatchRule_record)
 // CHECK-NEXT: MIGServerRoutine (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_block)
+// CHECK-NEXT: MSConstexpr (SubjectMatchRule_function)
 // CHECK-NEXT: MSStruct (SubjectMatchRule_record)
 // CHECK-NEXT: MaybeUndef (SubjectMatchRule_variable_is_parameter)
 // CHECK-NEXT: MicroMips (SubjectMatchRule_function)
Index: clang/test/AST/msvc-constexpr-new.cpp
===
--- /dev/null
+++ clang/test/AST/msvc-constexpr-new.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fms-extensions -std=c++20 -ast-dump %s | FileCheck %s
+
+// CHECK: used operator new
+// CHECK: MSConstexprAttr 0x{{[0-9a-f]+}} 
+[[nodiscard]] [[msvc::constexpr]] inline void* __cdecl operator new(decltype(sizeof(void*)), void* p) noexcept { return p; }
+
+// CHECK: used constexpr construct_at
+// CHECK: AttributedStmt 0x{{[0-9a-f]+}} 
+// CHECK-NEXT: MSConstexprAttr 0x{{[0-9a-f]+}} 
+// CHECK-NEXT: ReturnStmt 0x{{[0-9a-f]+}} 
+constexpr int* construct_at(int* p, int v) { [[msvc::constexpr]] return ::new (p) int(v); }
+
+constexpr bool check_construct_at() { int x; return *construct_at(&x, 42) == 42; }
+
+static_assert(check_construct_at());
Index: clang/test/AST/msvc-attrs.cpp
===
--- /dev/null
+++ clang/test/AST/msvc-attrs.cpp
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -fms-extensions -std=c++20 -ast-dump %s | FileCheck %s
+
+// [[msvc::constexpr]] tests
+
+// MSConstexprDocs (1)
+// CHECK: used f1 'bool ()'
+// CHECK: MSConstexprAttr 0x{{[0-9a-f]+}} 
+[[msvc::constexpr]] bool f1() { return true; }
+
+// MSConstexprDocs (2)
+// CHECK: used constexpr f2 'bool ()'
+// CHECK: AttributedStmt 0x{{[0-9a-f]+}} 
+// CHECK-NEXT: MSConstexprAttr 0x{{[0-9a-f]+}} 
+// CHECK-NEXT: ReturnStmt 0x{{[0-9a-f]+}} 
+constexpr bool f2() { [[msvc::constexpr]] return f1(); }
+
+static_assert(f2());
+
+constexpr bool f3() { [[msvc::constexpr]] return f1() || f1() && f1(); }
+static_assert(f3());
+
+[[msvc::constexpr]] int f4(int x) { [[msvc::constexpr]] return x > 1 ? 1 + f4(x / 2) : 0; }
+constexpr bool f5() { [[msvc::constexpr]] return f4(32) == 5; }
+static_assert(f5());
+
+[[msvc::constexpr]] int f6(int x)
+{
+switch (x)
+{
+case 42: return 1337;
+default:
+ if (x < 0) [[msvc::constexpr]] return f4(-x);
+ else return x;
+}
+}
+
+constexpr bool f7() { [[msvc::constexpr]] return f6(f6(42) - 133

[PATCH] D134475: [Clang] Add support for [[msvc::constexpr]] C++11 attribute

2023-04-21 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt planned changes to this revision.
RIscRIpt marked 2 inline comments as done.
RIscRIpt added a comment.

> Does it prohibit the inverse?  I think this documentation overall needs a 
> much better description of what the semantics are here, particularly anything 
> that you found in experimentation on the MS implementation.

Do you mean, can `[[msvc::constexpr]]` function call `constexpr` and remain 
const-evaluated? Yes.

From my experiments all Cody's points are valid, except for "An extended 
constexpr function can call other extended constexpr functions without a 
statement-level annotation".

I tried to make doc notes as compact as possible. Recapping his points, which 
were confirmed by tests:

1. `[[msvc::constexpr]]` can be applied only to function definition or a return 
statement.
2. A function can be either `constexpr` or `consteval` or 
`[[msvc::constexpr]]`, but no combination of these.
3. `[[msvc::constexpr]]` function is treated the same way as `constexpr` 
function if it is evaluated in terms of `[[msvc::constexpr]] return` statement, 
otherwise it's a regular function.

By function I mean anything function-like: functions, member-functions, 
constructors, destructors, operators.

In D134475#4287513 , @erichkeane 
wrote:

> Still suspicious about this/whether it models the MSVC implementation 
> correctly, but no real implementation concerns.  I REALLY want us to document 
> the attribute extensively however.

Thanks to your concern I decided to test each point of `[dcl.constexpr]` : 
`9.2.6 The constexpr and consteval specifiers` in Compiler Explorer: 
https://godbolt.org/z/qj3fnK5aW I am going to update tests accordingly.

Regarding on absolute matching MSVC implementation, I am not sure we will be 
able to achieve it with reasonable changes. I am skeptical, because I 
discovered the following test case:

  struct S2 {
  [[msvc::constexpr]] S2() {}
  [[msvc::constexpr]] bool value() { return true; } 
  static constexpr bool check() { [[msvc::constexpr]] return S2{}.value(); }
  };
  static_assert(S2::check());

It's a valid code for MSVC; nothing special https://godbolt.org/z/znnaonEhM
However supporting this code seems to be difficult in Clang:

1. S2 fails checks of "literal type" in this callstack:
  1. [[ 
https://github.com/llvm/llvm-project/blob/bc73ef0/clang/include/clang/AST/DeclCXX.h#L1419-L1445
 | `clang::CXXRecordDecl::isLiteral` ]]
  2. [[ 
https://github.com/llvm/llvm-project/blob/e98776a/clang/lib/AST/Type.cpp#L2746 
| `clang::Type::isLiteralType` ]]
  3. [[ 
https://github.com/llvm/llvm-project/blob/a4edc2c/clang/lib/AST/ExprConstant.cpp#L2317-L2320
 | `CheckLiteralType` ]]
2. We have information about CanEvalMSConstexpr only in `CheckLiteralType`. So, 
currently, I don't see how we can reasonably check whether `S2` is a valid 
literal type in context of `[[msvc::constexpr]]`. Two obvious **ugly** 
solutions are:
  1. Copy all checks from `clang::CXXRecordDecl::isLiteral` to 
`CheckLiteralType` - violates DRY; two places shall be maintained.
  2. Propagate `CanEvalMSConstexpr` down to `clang::CXXRecordDecl::isLiteral`. 
I don't think it's reasonable for supporting rare vendor-specific attribute.




Comment at: clang/include/clang/Basic/AttrDocs.td:3543
+definition or a return statement. It has no effect on function declarations.
+This attribute permits constant evaluation of ``[[msvc::constexpr]]`` functions
+in ``[[msvc::constexpr]] return`` statements inside ``constexpr`` or

erichkeane wrote:
> Does it prohibit the inverse?  I think this documentation overall needs a 
> much better description of what the semantics are here, particularly anything 
> that you found in experimentation on the MS implementation.
> Does it prohibit the inverse?
Do you mean, can `[[msvc::constexpr]]` function call `constexpr` and remain 
const-evaluated? Yes.

I elaborated on semantics in non-inline comment.



Comment at: clang/lib/Sema/SemaDeclAttr.cpp:7057-7058
+static void handleMSConstexprAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+  if (auto *FD = dyn_cast(D))
+FD->setConstexprKind(ConstexprSpecKind::Constexpr);
+  D->addAttr(::new (S.Context) MSConstexprAttr(S.Context, AL));

RIscRIpt wrote:
> aaron.ballman wrote:
> > We can use `cast` here because we know the declaration must have already 
> > been determined to be a function (from the subjects list in Attr.td).
> > 
> > That said, I think there's more semantic checking we want to do here. For 
> > example, can you use this attribute on a virtual function? What about a 
> > function already marked `constexpr`? Even more scary, what about a function 
> > marked `consteval`?
> > 
> > Also, I presume a `constexpr` function should be able to call an 
> > `[[msvc::constexpr]]` function and vice versa?
> > We can use cast here because we know the declaration must have already been 
> > determined to be a funct

[PATCH] D133853: [AST] Add msvc-specific C++11 attributes

2022-09-22 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt abandoned this revision.
RIscRIpt added a comment.

Closing in favor of https://reviews.llvm.org/D134458


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133853

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


[PATCH] D134458: [AST] Add msvc-specific C++11 attribute 'msvc::no_unique_address'

2022-09-22 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 462274.
RIscRIpt retitled this revision from "[AST] Add msvc-specific C++11 attributes" 
to "[AST] Add msvc-specific C++11 attribute 'msvc::no_unique_address'".
RIscRIpt added a comment.

Remove msvc::constexpr commit


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134458

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/Attr.td
  clang/lib/AST/Decl.cpp
  clang/lib/AST/RecordLayoutBuilder.cpp
  clang/lib/CodeGen/CGExprAgg.cpp
  clang/lib/CodeGen/CGExprConstant.cpp
  clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
  clang/lib/CodeGen/TargetInfo.cpp
  clang/test/AST/msvc-attrs.cpp

Index: clang/test/AST/msvc-attrs.cpp
===
--- clang/test/AST/msvc-attrs.cpp
+++ clang/test/AST/msvc-attrs.cpp
@@ -1,6 +1,14 @@
 // RUN: %clang_cc1 -fms-extensions -std=c++20 -ast-dump %s | FileCheck %s
-// RUN: not %clang_cc1 -Werror=ignored-attributes -ast-dump %s 2>&1 | grep "1 error generated"
+// RUN: not %clang_cc1 -Werror=ignored-attributes -ast-dump %s 2>&1 | grep "3 errors generated"
 
-// CHECK: msvc-attrs.cpp:[[@LINE+2]]:21, col:61> col:27 constexpr New1 'void *(void *)'
+struct Empty {};
+
+// CHECK:  col:27 constexpr New1 'void *(void *)'
 // CHECK: MSConstexprAttr 0x{{[0-9a-f]+}} 
 [[msvc::constexpr]] void *New1(void *where) { return where; }
+
+struct StructWithNUAField {
+  [[msvc::no_unique_address]] Empty e;
+  int f1;
+};
+static_assert(sizeof(StructWithNUAField) == sizeof(int)); // expected to fail without -fms-extensions
Index: clang/lib/CodeGen/TargetInfo.cpp
===
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -578,8 +578,7 @@
   // according to the Itanium ABI.  The exception applies only to records,
   // not arrays of records, so we must also check whether we stripped off an
   // array type above.
-  if (isa(RT->getDecl()) &&
-  (WasArray || !FD->hasAttr()))
+  if (isa(RT->getDecl()) && (WasArray || !FD->hasNoUniqueAddress()))
 return false;
 
   return isEmptyRecord(Context, FT, AllowArrays);
@@ -7524,8 +7523,7 @@
   // do count.  So do anonymous bitfields that aren't zero-sized.
 
   // Like isSingleElementStruct(), ignore C++20 empty data members.
-  if (FD->hasAttr() &&
-  isEmptyRecord(getContext(), FD->getType(), true))
+  if (FD->hasNoUniqueAddress() && isEmptyRecord(getContext(), FD->getType(), true))
 continue;
 
   // Unlike isSingleElementStruct(), arrays do not count.
Index: clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
===
--- clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -744,7 +744,7 @@
 Prior->Data = getByteArrayType(bitsToCharUnits(llvm::alignTo(
 cast(Prior->Data)->getIntegerBitWidth(), 8)));
   else {
-assert(Prior->FD->hasAttr() &&
+assert(Prior->FD->hasNoUniqueAddress() &&
"should not have reused this field's tail padding");
 Prior->Data = getByteArrayType(
 Context.getTypeInfoDataSizeInChars(Prior->FD->getType()).Width);
Index: clang/lib/CodeGen/CGExprConstant.cpp
===
--- clang/lib/CodeGen/CGExprConstant.cpp
+++ clang/lib/CodeGen/CGExprConstant.cpp
@@ -755,7 +755,7 @@
 return false;
   // After emitting a non-empty field with [[no_unique_address]], we may
   // need to overwrite its tail padding.
-  if (Field->hasAttr())
+  if (Field->hasNoUniqueAddress())
 AllowOverwrite = true;
 } else {
   // Otherwise we have a bitfield.
@@ -856,7 +856,7 @@
 return false;
   // After emitting a non-empty field with [[no_unique_address]], we may
   // need to overwrite its tail padding.
-  if (Field->hasAttr())
+  if (Field->hasNoUniqueAddress())
 AllowOverwrite = true;
 } else {
   // Otherwise we have a bitfield.
Index: clang/lib/CodeGen/CGExprAgg.cpp
===
--- clang/lib/CodeGen/CGExprAgg.cpp
+++ clang/lib/CodeGen/CGExprAgg.cpp
@@ -2015,7 +2015,7 @@
 
 AggValueSlot::Overlap_t
 CodeGenFunction::getOverlapForFieldInit(const FieldDecl *FD) {
-  if (!FD->hasAttr() || !FD->getType()->isRecordType())
+  if (!FD->hasNoUniqueAddress() || !FD->getType()->isRecordType())
 return AggValueSlot::DoesNotOverlap;
 
   // If the field lies entirely within the enclosing class's nvsize, its tail
Index: clang/lib/AST/RecordLayoutBuilder.cpp
===
--- clang/lib/AST/RecordLayoutBuilder.cpp
+++ clang/lib/AST/RecordLayoutBuilder.cpp
@@ -474,7 +474,7 @@
 
   // We are able to place the member variable at this offset.
   // Make sure to 

[PATCH] D134475: [AST] Add C++11 attribute msvc::constexpr

2022-09-22 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt created this revision.
Herald added a reviewer: aaron.ballman.
Herald added a subscriber: jdoerfert.
Herald added a project: All.
RIscRIpt requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D134475

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/AST/msvc-attrs.cpp
  clang/test/Misc/pragma-attribute-supported-attributes-list.test


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
@@ -83,6 +83,7 @@
 // CHECK-NEXT: LoaderUninitialized (SubjectMatchRule_variable_is_global)
 // CHECK-NEXT: Lockable (SubjectMatchRule_record)
 // CHECK-NEXT: MIGServerRoutine (SubjectMatchRule_function, 
SubjectMatchRule_objc_method, SubjectMatchRule_block)
+// CHECK-NEXT: MSConstexpr (SubjectMatchRule_function)
 // CHECK-NEXT: MSStruct (SubjectMatchRule_record)
 // CHECK-NEXT: MaybeUndef (SubjectMatchRule_variable_is_parameter)
 // CHECK-NEXT: MicroMips (SubjectMatchRule_function)
Index: clang/test/AST/msvc-attrs.cpp
===
--- /dev/null
+++ clang/test/AST/msvc-attrs.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -fms-extensions -std=c++20 -ast-dump %s | FileCheck %s
+// RUN: not %clang_cc1 -Werror=ignored-attributes -ast-dump %s 2> %t.stderr.txt
+// RUN: FileCheck -check-prefix CHECK-DIAG-NO-MSX %s < %t.stderr.txt
+
+// CHECK: msvc-attrs.cpp:[[@LINE+3]]:21, col:61> col:27 constexpr New1 'void 
*(void *)'
+// CHECK: MSConstexprAttr 0x{{[0-9a-f]+}} 
+// CHECK-DIAG-NO-MSX: msvc-attrs.cpp:[[@LINE+1]]:3: error: 'constexpr' 
attribute ignored
+[[msvc::constexpr]] void *New1(void *where) { return where; }
Index: clang/lib/Sema/SemaDeclAttr.cpp
===
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -4992,6 +4992,9 @@
   case ParsedAttr::AT_PreserveAll:
 D->addAttr(::new (S.Context) PreserveAllAttr(S.Context, AL));
 return;
+  case ParsedAttr::AT_MSConstexpr:
+D->addAttr(::new (S.Context) MSConstexprAttr(S.Context, AL));
+return;
   default:
 llvm_unreachable("unexpected attribute kind");
   }
@@ -7050,6 +7053,12 @@
   D->addAttr(::new (S.Context) ThreadAttr(S.Context, AL));
 }
 
+static void handleMSConstexprAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+  if (auto *FD = dyn_cast(D))
+FD->setConstexprKind(ConstexprSpecKind::Constexpr);
+  D->addAttr(::new (S.Context) MSConstexprAttr(S.Context, AL));
+}
+
 static void handleAbiTagAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   SmallVector Tags;
   for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
@@ -8987,6 +8996,9 @@
   case ParsedAttr::AT_Thread:
 handleDeclspecThreadAttr(S, D, AL);
 break;
+  case ParsedAttr::AT_MSConstexpr:
+handleMSConstexprAttr(S, D, AL);
+break;
 
   // HLSL attributes:
   case ParsedAttr::AT_HLSLNumThreads:
Index: clang/include/clang/Basic/AttrDocs.td
===
--- clang/include/clang/Basic/AttrDocs.td
+++ clang/include/clang/Basic/AttrDocs.td
@@ -3478,6 +3478,14 @@
 }];
 }
 
+def MSConstexprDocs : Documentation {
+  let Category = DocCatStmt;
+  let Content = [{
+This attribute is an alias of ``constexpr`` for functions.
+Available only as Microsoft extension (``-fms-extensions``).
+  }];
+}
+
 def MSNoVTableDocs : Documentation {
   let Category = DocCatDecl;
   let Content = [{
Index: clang/include/clang/Basic/Attr.td
===
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -3500,6 +3500,13 @@
 
 // Microsoft-related attributes
 
+def MSConstexpr : InheritableAttr {
+  let LangOpts = [MicrosoftExt];
+  let Spellings = [CXX11<"msvc", "constexpr">];
+  let Subjects = SubjectList<[Function]>;
+  let Documentation = [MSConstexprDocs];
+}
+
 def MSNoVTable : InheritableAttr, TargetSpecificAttr {
   let Spellings = [Declspec<"novtable">];
   let Subjects = SubjectList<[CXXRecord]>;


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
@@ -83,6 +83,7 @@
 // CHECK-NEXT: LoaderUninitialized (SubjectMatchRule_variable_is_global)
 // CHECK-NEXT: Lockable (SubjectMatchRule_record)
 // CHECK-NEXT: MIGServerRoutine (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_block)
+// CHECK-NEXT: MSConstexpr (SubjectMatchRule_function)
 // CHECK-NEXT: MSStruct (SubjectMatchRule

[PATCH] D134458: [AST] Add msvc-specific C++11 attribute 'msvc::no_unique_address'

2022-09-22 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added a comment.

In D134458#3809570 , @aaron.ballman 
wrote:

> Can you split this out into two separate reviews?

Sure, done: https://reviews.llvm.org/D134475




Comment at: clang/include/clang/Basic/Attr.td:3497
+
+def MSNoUniqueAddress : InheritableAttr, 
TargetSpecificAttr {
+  let LangOpts = [MicrosoftExt];

aaron.ballman wrote:
> Hmmm, very odd that the msvc no unique address attribute is only supported on 
> Itanium ABI targets. Should this be `TargetMicrosoftCXXABI` instead?
My fault, I did blind copy-paste completely forgetting about ABI!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134458

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


[PATCH] D134458: [AST] Add C++11 attribute 'msvc::no_unique_address'

2022-09-22 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 462297.
RIscRIpt retitled this revision from "[AST] Add msvc-specific C++11 attribute 
'msvc::no_unique_address'" to "[AST] Add C++11 attribute 
'msvc::no_unique_address'".
RIscRIpt added a comment.

Add naive implementation ABI of [[msvc::no_unique_address]]


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134458

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/Attr.td
  clang/lib/AST/Decl.cpp
  clang/lib/AST/RecordLayoutBuilder.cpp
  clang/lib/CodeGen/CGExprAgg.cpp
  clang/lib/CodeGen/CGExprConstant.cpp
  clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
  clang/lib/CodeGen/TargetInfo.cpp
  clang/test/AST/msvc-attrs.cpp

Index: clang/test/AST/msvc-attrs.cpp
===
--- /dev/null
+++ clang/test/AST/msvc-attrs.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fms-extensions -fc++-abi=microsoft -triple=x86_64-pc-windows-msvc -std=c++20 -ast-dump %s | FileCheck %s
+// RUN: not %clang_cc1 -Werror=ignored-attributes -ast-dump %s 2> %t.stderr.txt
+// RUN: FileCheck -check-prefix CHECK-DIAG-NO-MSX %s < %t.stderr.txt
+
+struct Empty {};
+
+struct StructWithNUAField {
+  // CHECK: FieldDecl 0x{{[0-9a-f]+}}  col:37 e 'Empty':'Empty'
+  // CHECK-NEXT: MSNoUniqueAddressAttr
+  [[msvc::no_unique_address]] Empty e;
+  int f1;
+};
+
+// CHECK-DIAG-NO-MSX: msvc-attrs.cpp:[[@LINE+1]]:1: error: static assertion failed due to requirement 'sizeof(StructWithNUAField) == sizeof(int)' 
+static_assert(sizeof(StructWithNUAField) == sizeof(int));
Index: clang/lib/CodeGen/TargetInfo.cpp
===
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -578,8 +578,7 @@
   // according to the Itanium ABI.  The exception applies only to records,
   // not arrays of records, so we must also check whether we stripped off an
   // array type above.
-  if (isa(RT->getDecl()) &&
-  (WasArray || !FD->hasAttr()))
+  if (isa(RT->getDecl()) && (WasArray || !FD->hasNoUniqueAddress()))
 return false;
 
   return isEmptyRecord(Context, FT, AllowArrays);
@@ -7523,8 +7522,7 @@
   // do count.  So do anonymous bitfields that aren't zero-sized.
 
   // Like isSingleElementStruct(), ignore C++20 empty data members.
-  if (FD->hasAttr() &&
-  isEmptyRecord(getContext(), FD->getType(), true))
+  if (FD->hasNoUniqueAddress() && isEmptyRecord(getContext(), FD->getType(), true))
 continue;
 
   // Unlike isSingleElementStruct(), arrays do not count.
Index: clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
===
--- clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -744,7 +744,7 @@
 Prior->Data = getByteArrayType(bitsToCharUnits(llvm::alignTo(
 cast(Prior->Data)->getIntegerBitWidth(), 8)));
   else {
-assert(Prior->FD->hasAttr() &&
+assert(Prior->FD->hasNoUniqueAddress() &&
"should not have reused this field's tail padding");
 Prior->Data = getByteArrayType(
 Context.getTypeInfoDataSizeInChars(Prior->FD->getType()).Width);
Index: clang/lib/CodeGen/CGExprConstant.cpp
===
--- clang/lib/CodeGen/CGExprConstant.cpp
+++ clang/lib/CodeGen/CGExprConstant.cpp
@@ -755,7 +755,7 @@
 return false;
   // After emitting a non-empty field with [[no_unique_address]], we may
   // need to overwrite its tail padding.
-  if (Field->hasAttr())
+  if (Field->hasNoUniqueAddress())
 AllowOverwrite = true;
 } else {
   // Otherwise we have a bitfield.
@@ -856,7 +856,7 @@
 return false;
   // After emitting a non-empty field with [[no_unique_address]], we may
   // need to overwrite its tail padding.
-  if (Field->hasAttr())
+  if (Field->hasNoUniqueAddress())
 AllowOverwrite = true;
 } else {
   // Otherwise we have a bitfield.
Index: clang/lib/CodeGen/CGExprAgg.cpp
===
--- clang/lib/CodeGen/CGExprAgg.cpp
+++ clang/lib/CodeGen/CGExprAgg.cpp
@@ -2015,7 +2015,7 @@
 
 AggValueSlot::Overlap_t
 CodeGenFunction::getOverlapForFieldInit(const FieldDecl *FD) {
-  if (!FD->hasAttr() || !FD->getType()->isRecordType())
+  if (!FD->hasNoUniqueAddress() || !FD->getType()->isRecordType())
 return AggValueSlot::DoesNotOverlap;
 
   // If the field lies entirely within the enclosing class's nvsize, its tail
Index: clang/lib/AST/RecordLayoutBuilder.cpp
===
--- clang/lib/AST/RecordLayoutBuilder.cpp
+++ clang/lib/AST/RecordLayoutBuilder.cpp
@@ -474,7 +474,7 @@
 
   // We are able to place the member variable at this offset.
   // Make sure to update 

[PATCH] D134458: [AST] Add C++11 attribute 'msvc::no_unique_address'

2022-09-22 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt planned changes to this revision.
RIscRIpt added a comment.

TODO: add proper ABI tests of `[[msvc::no_unique_address]]`


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134458

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


[PATCH] D134475: Add C++11 attribute msvc::constexpr

2022-10-01 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 464522.
RIscRIpt retitled this revision from "[AST] Add C++11 attribute 
msvc::constexpr" to "Add C++11 attribute msvc::constexpr".
RIscRIpt added a comment.

Add more tests, don't alter constexprKind of `[[msvc::constexpr]]` functions - 
instead change implementation of `isConstexpr`

In D134475#3827712 , @aaron.ballman 
wrote:

> ... we're missing some significant test coverage for it. I had some 
> suggestions for specific things we should be thinking about, but another 
> useful test would be to modify an existing constexpr test to add a RUN line 
> enabling ms extensions, and use a macro to switch between `constexpr` and 
> `[[msvc::constexpr]]` based on those RUN lines. Basically, ensure that 
> `[[msvc::constexpr]]` gives the same behavior (both in terms of evaluation 
> and in terms of semantic checking) as `constexpr`. WDYT?

That's a good idea. Based on my experiments with MSVC, I am more convinced that 
`constexpr` and `[[msvc::constexpr]]` are synonyms (with some extra 
undocumented (yet?) features by MSFT). I added more tests as per your 
suggestion.
Regarding existing tests, I was able to find only 
`clang/test/AST/Interp/functions.cpp` which uses `constexpr` only with 
functions (otherwise `-Dconstexpr=[[msvc::constexpr]]` would break code in case 
there are `constexpr` variables) - I added `RUN` lines there.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134475

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/AST/Decl.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/AST/Interp/functions.cpp
  clang/test/AST/msvc-attrs-invalid.cpp
  clang/test/AST/msvc-attrs.cpp
  clang/test/Misc/pragma-attribute-supported-attributes-list.test

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
@@ -83,6 +83,7 @@
 // CHECK-NEXT: LoaderUninitialized (SubjectMatchRule_variable_is_global)
 // CHECK-NEXT: Lockable (SubjectMatchRule_record)
 // CHECK-NEXT: MIGServerRoutine (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_block)
+// CHECK-NEXT: MSConstexpr (SubjectMatchRule_function)
 // CHECK-NEXT: MSStruct (SubjectMatchRule_record)
 // CHECK-NEXT: MaybeUndef (SubjectMatchRule_variable_is_parameter)
 // CHECK-NEXT: MicroMips (SubjectMatchRule_function)
Index: clang/test/AST/msvc-attrs.cpp
===
--- /dev/null
+++ clang/test/AST/msvc-attrs.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -fms-extensions -std=c++20 -ast-dump %s | FileCheck %s
+// RUN: not %clang_cc1 -Werror=ignored-attributes -ast-dump %s 2> %t.stderr.txt
+// RUN: FileCheck -check-prefix CHECK-DIAG-NO-MSX %s < %t.stderr.txt
+
+// CHECK: msvc-attrs.cpp:[[@LINE+3]]:21, col:32> col:26 f0 'void ()'
+// CHECK: MSConstexprAttr 0x{{[0-9a-f]+}} 
+// CHECK-DIAG-NO-MSX: msvc-attrs.cpp:[[@LINE+1]]:3: error: 'constexpr' attribute ignored
+[[msvc::constexpr]] void f0() {}
+
+struct s0 {
+  // CHECK: CXXConstructorDecl 0x{{[0-9a-f]+}}  col:23 s0 'void ()' implicit-inline
+  // CHECK: MSConstexprAttr 0x{{[0-9a-f]+}} 
+  [[msvc::constexpr]] s0() {}
+
+  // CHECK: CXXDestructorDecl 0x{{[0-9a-f]+}}  col:23 ~s0 'void () noexcept' implicit-inline
+  // CHECK: MSConstexprAttr 0x{{[0-9a-f]+}} 
+  [[msvc::constexpr]] ~s0() {}
+
+  // CHECK: CXXMethodDecl 0x{{[0-9a-f]+}}  col:36 used f1 'void ()' virtual implicit-inline
+  // CHECK: MSConstexprAttr 0x{{[0-9a-f]+}} 
+  [[msvc::constexpr]] virtual void f1() {}
+};
+
+// Check 'constexpr' and '[[msvc::constexpr]]' functions can call each other
+void f2();
+constexpr void f3();
+
+[[msvc::constexpr]] void f2() { f3(); }
+constexpr void f3() { f2(); }
+
+[[msvc::constexpr]] void f4();
+constexpr void f5();
+
+void f4() { f5(); }
+constexpr void f5() { f4(); }
Index: clang/test/AST/msvc-attrs-invalid.cpp
===
--- /dev/null
+++ clang/test/AST/msvc-attrs-invalid.cpp
@@ -0,0 +1,14 @@
+// RUN: not %clang_cc1 -fms-extensions -std=c++20 -ast-dump %s 2> %t.stderr.txt
+// RUN: FileCheck %s < %t.stderr.txt
+
+void runtime() {}
+
+// CHECK: msvc-attrs-invalid.cpp:[[@LINE+1]]:26: error: constexpr function never produces a constant expression [-Winvalid-constexpr]
+[[msvc::constexpr]] void f0() { runtime(); }
+
+// CHECK: msvc-attrs-invalid.cpp:[[@LINE+1]]:3: error: {{\[\[}}msvc::constexpr{{]]}} cannot be applied to a 'constexpr' or 'consteval' function 'f1'
+[[msvc::constexpr]] constexpr void f1() {}
+
+// CHECK: msvc-attrs-invalid.cpp:[[@LINE+1]]:3: error: {{\[\[}}msvc::constexpr{{]]}

[PATCH] D134475: Add C++11 attribute msvc::constexpr

2022-10-01 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt planned changes to this revision.
RIscRIpt added inline comments.



Comment at: clang/lib/Sema/SemaDeclAttr.cpp:4995-4997
+  case ParsedAttr::AT_MSConstexpr:
+D->addAttr(::new (S.Context) MSConstexprAttr(S.Context, AL));
+return;

aaron.ballman wrote:
> This looks incorrect to me -- constexpr isn't a calling convention, so I 
> think this code should be removed.
Oops, removed.



Comment at: clang/lib/Sema/SemaDeclAttr.cpp:7057-7058
+static void handleMSConstexprAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+  if (auto *FD = dyn_cast(D))
+FD->setConstexprKind(ConstexprSpecKind::Constexpr);
+  D->addAttr(::new (S.Context) MSConstexprAttr(S.Context, AL));

aaron.ballman wrote:
> We can use `cast` here because we know the declaration must have already been 
> determined to be a function (from the subjects list in Attr.td).
> 
> That said, I think there's more semantic checking we want to do here. For 
> example, can you use this attribute on a virtual function? What about a 
> function already marked `constexpr`? Even more scary, what about a function 
> marked `consteval`?
> 
> Also, I presume a `constexpr` function should be able to call an 
> `[[msvc::constexpr]]` function and vice versa?
> We can use cast here because we know the declaration must have already been 
> determined to be a function (from the subjects list in Attr.td).

Indeed. Changed.

> That said, I think there's more semantic checking we want to do here. For 
> example, can you use this attribute on a virtual function? What about a 
> function already marked constexpr? Even more scary, what about a function 
> marked consteval?

Good questions. By running `strings c1xx.dll` I was able to find only the 
following diagnostic messages regarding `[[msvc::constexpr]]`:
```
[[msvc::constexpr]] may only be applied to statements and functions"
[[msvc::constexpr]] cannot be applied to a 'constexpr' or 'consteval' function"
```

I've made a similar check here and added relevant test cases in 
`msvc-attrs-invalid.cpp`. But in order to make it possible, I had to change 
`FunctionDecl::isConstexpr()`, please check new changes.

//TODO//: I think, I'll need to read more about `constexpr` for functions in 
standard (and LLVM code), to add relevant restrictions here.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134475

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


[PATCH] D134475: Add C++11 attribute msvc::constexpr

2022-10-02 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added a comment.

> TODO: I think, I'll need to read more about constexpr for functions in 
> standard (and LLVM code), to add relevant restrictions here.

In the standard I was able to find the following paragraphs about `constexpr`:

1. Neither constructor nor destructor can be constexpr if the class has some 
virtual base class; this holds for `[[msvc::constexpr]]` in MSVC 14.33
2. `constexpr` is not a part of function signature, so same non-constexpr 
function cannot be defined. The same holds for C++11 attributes, and 
`[[msvc::constexpr]]` in MSVC 14.33

I will add two relevant tests in `msvc-attrs-invalid.cpp`

Regarding LLVM code, I made the following observations:

- `FunctionDecl::isConstexprSpecified()` is mostly used for printing code, in 
other words, to check that the function is `constexpr` (and not `consteval`).
- `FunctionDecl::getConstexprKind()` is used by:
- `ASTImporter.cpp` - seems that, it should take care of attributes 
independently from the `getConstexprKind()`
- `ASTWriterDecl.cpp` - seems that, it should take care of attributes 
independently from the `getConstexprKind()`
- `SemaDecl.cpp` / `SemaDeclCXX.cpp` - checks that re-declaration was not 
performed with different constexpr specifier. MSVC and clang with current 
implementation allows re-declaration with different attributes (there are tests 
with `f2-f5` in `msvc-attrs.cpp`)
- `SemaDeclCXX` - enables C++ constexpr constructor inheritance - problem - my 
current implementation supports it, whereas MSVC doesn't:

  // Check '[[msvc::constexpr]]' is not taken into account during constructor 
inheritance
  struct s2 {
  [[msvc::constexpr]] s2() {}
  constexpr operator bool() { return false; };
  };
  
  struct s3 : s2 {
  constexpr operator bool() { return true; };
  };
  static_assert(s3()); // MSVC: C2131: expression did not evaluate to a constant
  static_assert(s3()); // clang with my patch: OK

- `SemaTemplate.cpp` - enables C++ template re-specialization with different 
constexpr specifier, not a problem, because we are allowed to do the same with 
attributes (don't we?)
- `SemaTemplateInstantiateDecl.cpp` (`TemplateDeclInstantiator`) - enables C++ 
template instantiation with same constexpr specifier

  template
  struct s1 {
  [[msvc::constexpr]] s1() {}
  constexpr operator bool() { return true; };
  };
  
  static_assert(s1()); // MSVC: C2131: expression did not evaluate to a 
constant
  static_assert(s1()); // clang with my patch: OK

- `TreeTransform.h` - code is related to lambdas - out-of-scope of the current 
patch.

Regarding `MSVC:C2131` I found one more problem:

  [[msvc::constexpr]] int C() { return 0; }
  constexpr int V = C(); // MSVC: C2131: expression did not evaluate to a 
constant
  constexpr int W = C(); // clang with my patch: OK

I am starting to question my patch - does LLVM really need it, if

1. There's no documentation for `[[msvc::constexpr]]`
2. The trivial implementation makes it an alias, but the semantic behavior is 
different - we could fix that, but there are lots of things to check

@aaron.ballman WDYT?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134475

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


[PATCH] D134458: [AST] Add C++11 attribute 'msvc::no_unique_address'

2023-11-04 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt abandoned this revision.
RIscRIpt added a comment.

Abandoning due to lack of time and expertise. I might come back and tackle it 
in several months.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134458

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


[PATCH] D134475: [clang-cl] Add support for [[msvc::constexpr]] C++11 attribute

2023-11-04 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt abandoned this revision.
RIscRIpt added a comment.

As per agreement, migrating to Github: 
https://github.com/llvm/llvm-project/pull/71300


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134475

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


[PATCH] D153914: [clang-cl] Enable concatenation of predefined identifiers

2023-08-08 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 548274.
RIscRIpt added a comment.

Rebased onto main, run local lit clang/tests. (bump for @cor3ntin)
As far as I understand this shall be merged into main by maintainers.
Please let me know if something else is expected from me.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153914

Files:
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Lex/LiteralSupport.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Lex/LiteralSupport.cpp
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/Sema/ms_predefined_expr.cpp
  clang/test/Sema/ms_wide_predefined_expr.cpp

Index: clang/test/Sema/ms_wide_predefined_expr.cpp
===
--- clang/test/Sema/ms_wide_predefined_expr.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-// RUN: %clang_cc1 %s -fsyntax-only -Wno-unused-value -Wmicrosoft -verify -fms-extensions
-// expected-no-diagnostics
-
-// Wide character predefined identifiers
-#define _STR2WSTR(str) L##str
-#define STR2WSTR(str) _STR2WSTR(str)
-void abcdefghi12(void) {
- const wchar_t (*ss)[12] = &STR2WSTR(__FUNCTION__);
- static int arr[sizeof(STR2WSTR(__FUNCTION__))==12*sizeof(wchar_t) ? 1 : -1];
- const wchar_t (*ss2)[31] = &STR2WSTR(__FUNCSIG__);
- static int arr2[sizeof(STR2WSTR(__FUNCSIG__))==31*sizeof(wchar_t) ? 1 : -1];
-}
-
-namespace PR13206 {
-void foo(const wchar_t *);
-
-template class A {
-public:
- void method() {
-  foo(L__FUNCTION__);
- }
-};
-
-void bar() {
- A x;
- x.method();
-}
-}
Index: clang/test/Sema/ms_predefined_expr.cpp
===
--- clang/test/Sema/ms_predefined_expr.cpp
+++ clang/test/Sema/ms_predefined_expr.cpp
@@ -1,9 +1,170 @@
 // RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-extensions
 
-void f() {
+using size_t = __SIZE_TYPE__;
+
+// Test array initialization
+void array_init() {
  const char a[] = __FUNCTION__; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
  const char b[] = __FUNCDNAME__; // expected-warning{{initializing an array from a '__FUNCDNAME__' predefined identifier is a Microsoft extension}}
  const char c[] = __FUNCSIG__; // expected-warning{{initializing an array from a '__FUNCSIG__' predefined identifier is a Microsoft extension}}
  const char d[] = __func__; // expected-warning{{initializing an array from a '__func__' predefined identifier is a Microsoft extension}}
  const char e[] = __PRETTY_FUNCTION__; // expected-warning{{initializing an array from a '__PRETTY_FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t f[] = L__FUNCTION__; // expected-warning{{initializing an array from a 'L__FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t g[] = L__FUNCSIG__; // expected-warning{{initializing an array from a 'L__FUNCSIG__' predefined identifier is a Microsoft extension}}
+}
+
+// Test function local identifiers outside of a function
+const char* g_function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+const char* g_function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+const char* g_function_rconcat = __FUNCTION__ ""; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+
+namespace NS
+{
+  const char* function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+  const char* function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+  const char* function_rconcat = __FUNCTION__ ""; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+
+  struct S
+  {
+static constexpr const char* function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+static constexpr const char* function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}}

[PATCH] D153914: [clang-cl] Enable concatenation of predefined identifiers

2023-08-08 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 548366.
RIscRIpt marked 4 inline comments as done.
RIscRIpt added a comment.

Address review comments, rebase onto main


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153914

Files:
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Lex/LiteralSupport.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Lex/LiteralSupport.cpp
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/Sema/ms_predefined_expr.cpp
  clang/test/Sema/ms_wide_predefined_expr.cpp

Index: clang/test/Sema/ms_wide_predefined_expr.cpp
===
--- clang/test/Sema/ms_wide_predefined_expr.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-// RUN: %clang_cc1 %s -fsyntax-only -Wno-unused-value -Wmicrosoft -verify -fms-extensions
-// expected-no-diagnostics
-
-// Wide character predefined identifiers
-#define _STR2WSTR(str) L##str
-#define STR2WSTR(str) _STR2WSTR(str)
-void abcdefghi12(void) {
- const wchar_t (*ss)[12] = &STR2WSTR(__FUNCTION__);
- static int arr[sizeof(STR2WSTR(__FUNCTION__))==12*sizeof(wchar_t) ? 1 : -1];
- const wchar_t (*ss2)[31] = &STR2WSTR(__FUNCSIG__);
- static int arr2[sizeof(STR2WSTR(__FUNCSIG__))==31*sizeof(wchar_t) ? 1 : -1];
-}
-
-namespace PR13206 {
-void foo(const wchar_t *);
-
-template class A {
-public:
- void method() {
-  foo(L__FUNCTION__);
- }
-};
-
-void bar() {
- A x;
- x.method();
-}
-}
Index: clang/test/Sema/ms_predefined_expr.cpp
===
--- clang/test/Sema/ms_predefined_expr.cpp
+++ clang/test/Sema/ms_predefined_expr.cpp
@@ -1,9 +1,170 @@
 // RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-extensions
 
-void f() {
+using size_t = __SIZE_TYPE__;
+
+// Test array initialization
+void array_init() {
  const char a[] = __FUNCTION__; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
  const char b[] = __FUNCDNAME__; // expected-warning{{initializing an array from a '__FUNCDNAME__' predefined identifier is a Microsoft extension}}
  const char c[] = __FUNCSIG__; // expected-warning{{initializing an array from a '__FUNCSIG__' predefined identifier is a Microsoft extension}}
  const char d[] = __func__; // expected-warning{{initializing an array from a '__func__' predefined identifier is a Microsoft extension}}
  const char e[] = __PRETTY_FUNCTION__; // expected-warning{{initializing an array from a '__PRETTY_FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t f[] = L__FUNCTION__; // expected-warning{{initializing an array from a 'L__FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t g[] = L__FUNCSIG__; // expected-warning{{initializing an array from a 'L__FUNCSIG__' predefined identifier is a Microsoft extension}}
+}
+
+// Test function local identifiers outside of a function
+const char* g_function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+const char* g_function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+const char* g_function_rconcat = __FUNCTION__ ""; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+
+namespace NS
+{
+  const char* function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+  const char* function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+  const char* function_rconcat = __FUNCTION__ ""; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+
+  struct S
+  {
+static constexpr const char* function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+static constexpr const char* function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+ // expected-warning{{expansion of pre

[PATCH] D153914: [clang-cl] Enable concatenation of predefined identifiers

2023-08-08 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added a comment.

In D153914#4570148 , @cor3ntin wrote:

> We will commit on your behalf, what name/email do you want us to use? 
> Thanks!

Thanks for asking; keep the name/email as-is in the commit you see: `Author: 
Richard Dzenis `




Comment at: clang/lib/Sema/Sema.cpp:1494-1505
+Decl *Sema::getCurLocalScopeDecl() {
+  if (const BlockScopeInfo *BSI = getCurBlock())
+return BSI->TheDecl;
+  else if (const LambdaScopeInfo *LSI = getCurLambda())
+return LSI->CallOperator;
+  else if (const CapturedRegionScopeInfo *CSI = getCurCapturedRegion())
+return CSI->TheCapturedDecl;

aaron.ballman wrote:
> Made the function `const` because it's not writing to any fields, removed 
> `else` because of preceding `return`.
I would love to, and I tried. But unfortunately it's not possible without 
introducing more changes: all the member functions (except 
`getCurFunctionOrMethodDecl()`) are non-const.
Removed `else`.



Comment at: clang/lib/Sema/SemaExpr.cpp:1998-2000
+if (isa(currentDecl)) {
+  Diag(Tok.getLocation(), diag::ext_predef_outside_function);
+}

aaron.ballman wrote:
> This will miss the diagnostic if the current declaration is a namespace 
> instead of at file scope, right?
Right. But `getCurLocalScopeDecl()` returns function scope at most. See Note in 
a code comment above.



Comment at: clang/lib/Sema/SemaExpr.cpp:2001-2004
+OS << '"'
+   << Lexer::Stringify(PredefinedExpr::ComputeName(
+  getPredefinedExprKind(Tok.getKind()), currentDecl))
+   << '"';

tahonermann wrote:
> RIscRIpt wrote:
> > tahonermann wrote:
> > > A diagnostic is issued if the call to `getCurScopeDecl()` returned a 
> > > translation unit declaration (at least in Microsoft mode). Does it make 
> > > sense to pass a pointer to a `TranslationUnitDecl` here?
> > Shortly, yes, kind of. `ComputeName` can handle `TranslationUnitDecl` in 
> > which case it returns an empty string. This way we implicitly (without 
> > additional code) create empty string-literal Tokens which can be handled in 
> > `StringLiteralParser`. And we cannot pass non-string-literal tokens into 
> > `StringLiteralParser`.
> Ah, ok. And I see it even differentiates what name is produced for 
> `__PRETTY_FUNCTION__`. That leaves me wondering what the right behavior 
> should be at class and namespace scope, but maybe I'm better off not asking 
> questions I don't want to know the answer to.
> A diagnostic is issued if the call to `getCurScopeDecl()` returned a 
> translation unit declaration (at least in Microsoft mode). Does it make sense 
> to pass a pointer to a `TranslationUnitDecl` here?




Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153914

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


[PATCH] D153914: [clang-cl] Enable concatenation of predefined identifiers

2023-08-09 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 548502.
RIscRIpt marked an inline comment as done.
RIscRIpt added a comment.

Updated comment; rebased onto main


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153914

Files:
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Lex/LiteralSupport.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Lex/LiteralSupport.cpp
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/Sema/ms_predefined_expr.cpp
  clang/test/Sema/ms_wide_predefined_expr.cpp

Index: clang/test/Sema/ms_wide_predefined_expr.cpp
===
--- clang/test/Sema/ms_wide_predefined_expr.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-// RUN: %clang_cc1 %s -fsyntax-only -Wno-unused-value -Wmicrosoft -verify -fms-extensions
-// expected-no-diagnostics
-
-// Wide character predefined identifiers
-#define _STR2WSTR(str) L##str
-#define STR2WSTR(str) _STR2WSTR(str)
-void abcdefghi12(void) {
- const wchar_t (*ss)[12] = &STR2WSTR(__FUNCTION__);
- static int arr[sizeof(STR2WSTR(__FUNCTION__))==12*sizeof(wchar_t) ? 1 : -1];
- const wchar_t (*ss2)[31] = &STR2WSTR(__FUNCSIG__);
- static int arr2[sizeof(STR2WSTR(__FUNCSIG__))==31*sizeof(wchar_t) ? 1 : -1];
-}
-
-namespace PR13206 {
-void foo(const wchar_t *);
-
-template class A {
-public:
- void method() {
-  foo(L__FUNCTION__);
- }
-};
-
-void bar() {
- A x;
- x.method();
-}
-}
Index: clang/test/Sema/ms_predefined_expr.cpp
===
--- clang/test/Sema/ms_predefined_expr.cpp
+++ clang/test/Sema/ms_predefined_expr.cpp
@@ -1,9 +1,170 @@
 // RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-extensions
 
-void f() {
+using size_t = __SIZE_TYPE__;
+
+// Test array initialization
+void array_init() {
  const char a[] = __FUNCTION__; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
  const char b[] = __FUNCDNAME__; // expected-warning{{initializing an array from a '__FUNCDNAME__' predefined identifier is a Microsoft extension}}
  const char c[] = __FUNCSIG__; // expected-warning{{initializing an array from a '__FUNCSIG__' predefined identifier is a Microsoft extension}}
  const char d[] = __func__; // expected-warning{{initializing an array from a '__func__' predefined identifier is a Microsoft extension}}
  const char e[] = __PRETTY_FUNCTION__; // expected-warning{{initializing an array from a '__PRETTY_FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t f[] = L__FUNCTION__; // expected-warning{{initializing an array from a 'L__FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t g[] = L__FUNCSIG__; // expected-warning{{initializing an array from a 'L__FUNCSIG__' predefined identifier is a Microsoft extension}}
+}
+
+// Test function local identifiers outside of a function
+const char* g_function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+const char* g_function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+const char* g_function_rconcat = __FUNCTION__ ""; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+
+namespace NS
+{
+  const char* function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+  const char* function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+  const char* function_rconcat = __FUNCTION__ ""; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+
+  struct S
+  {
+static constexpr const char* function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+static constexpr const char* function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+ // expected-warning{{expansion of predefined

[PATCH] D153914: [clang-cl] Enable concatenation of predefined identifiers

2023-08-09 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added inline comments.



Comment at: clang/lib/Sema/SemaExpr.cpp:2034-2035
 
+  // StringToks is read-only, we need backstorage for expanded macros
+  std::vector ExpandedToks;
+  if (getLangOpts().MicrosoftExt)

aaron.ballman wrote:
> 
Thanks, that's better. Changed in both places.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153914

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


[PATCH] D134475: [clang-cl] Add support for [[msvc::constexpr]] C++11 attribute

2023-08-11 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 549298.
RIscRIpt added a comment.

Rebase onto main (bump)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134475

Files:
  clang/docs/ReleaseNotes.rst
  clang/docs/UsersManual.rst
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/LangOptions.h
  clang/lib/AST/ExprConstant.cpp
  clang/lib/Basic/Targets/OSTargets.cpp
  clang/lib/Driver/ToolChains/MSVC.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaStmtAttr.cpp
  clang/test/AST/ms-constexpr.cpp
  clang/test/Driver/cl-options.c
  clang/test/Misc/pragma-attribute-supported-attributes-list.test
  clang/test/SemaCXX/ms-constexpr-invalid.cpp
  clang/test/SemaCXX/ms-constexpr-new.cpp
  clang/test/SemaCXX/ms-constexpr.cpp

Index: clang/test/SemaCXX/ms-constexpr.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/ms-constexpr.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++20 -verify %s
+// expected-no-diagnostics
+
+[[msvc::constexpr]] int log2(int x) { [[msvc::constexpr]] return x > 1 ? 1 + log2(x / 2) : 0; }
+constexpr bool test_log2() { [[msvc::constexpr]] return log2(32) == 5; }
+static_assert(test_log2());
+
+[[msvc::constexpr]] int get_value(int x)
+{
+  switch (x)
+  {
+case 42: return 1337;
+default:
+ if (x < 0) [[msvc::constexpr]] return log2(-x);
+ else return x;
+  }
+}
+
+constexpr bool test_complex_expr() {
+  [[msvc::constexpr]] return get_value(get_value(42) - 1337 + get_value(-32) - 5 + (get_value(1) ? get_value(0) : get_value(2))) == get_value(0);
+}
+static_assert(test_complex_expr());
+
+constexpr bool get_constexpr_true() { return true; }
+[[msvc::constexpr]] bool get_msconstexpr_true() { return get_constexpr_true(); }
+constexpr bool test_get_msconstexpr_true() { [[msvc::constexpr]] return get_msconstexpr_true(); }
+static_assert(test_get_msconstexpr_true());
+
+/*
+// TODO: Add support for [[msvc::constexpr]] constructor
+struct S2 {
+[[msvc::constexpr]] S2() {}
+[[msvc::constexpr]] bool value() { return true; }
+static constexpr bool check() { [[msvc::constexpr]] return S2{}.value(); }
+};
+static_assert(S2::check());
+*/
Index: clang/test/SemaCXX/ms-constexpr-new.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/ms-constexpr-new.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++20 -verify=supported %s
+// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.32 -std=c++20 -verify=unsupported %s
+// supported-no-diagnostics
+
+[[nodiscard]]
+[[msvc::constexpr]] // unsupported-warning {{unknown attribute 'constexpr' ignored}}
+inline void* __cdecl operator new(decltype(sizeof(void*)), void* p) noexcept { return p; }
+
+namespace std {
+  constexpr int* construct_at(int* p, int v) {
+[[msvc::constexpr]] return ::new (p) int(v); // unsupported-warning {{unknown attribute 'constexpr' ignored}}
+  }
+}
+
+constexpr bool check_construct_at() { int x; return *std::construct_at(&x, 42) == 42; }
+static_assert(check_construct_at());
Index: clang/test/SemaCXX/ms-constexpr-invalid.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/ms-constexpr-invalid.cpp
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++20 -verify %s
+// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++17 -verify %s
+
+// Check explicitly invalid code
+
+void runtime() {} // expected-note {{declared here}}
+
+[[msvc::constexpr]] void f0() { runtime(); } // expected-error {{[[msvc::constexpr]] function never produces a constant expression}} \
+ // expected-note {{non-constexpr function 'runtime' cannot be used in a constant expression}}
+[[msvc::constexpr]] constexpr void f1() {} // expected-error {{[[msvc::constexpr]] cannot be applied to a constexpr function 'f1'}}
+#if __cplusplus >= 202202L
+[[msvc::constexpr]] consteval void f2() {} // expected-error {{[[msvc::constexpr]] cannot be applied to a consteval function 'f2'}}
+#endif
+
+struct B1 {};
+struct D1 : virtual B1 { // expected-note {{virtual base class declared here}}
+[[msvc::constexpr]] D1() {} // expected-error {{constexpr constructor not allowed in struct with virtual base class}}
+};
+
+struct [[msvc::constexpr]] S2{}; // expected-error {{'constexpr' attribute only applies to functions and statements}}
+
+// Check invalid code mixed with valid code
+
+[[msvc::constexpr]] int f4(int x) { return x > 1 ? 1 + f4(x / 2) : 0; } // expected-note {{non-constexpr function 'f4' can

[PATCH] D157747: Support Unicode Microsoft predefined macros

2023-08-11 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt created this revision.
Herald added subscribers: PiotrZSL, carlosgalvezp, martong.
Herald added a reviewer: shafik.
Herald added a reviewer: njames93.
Herald added a project: All.
RIscRIpt requested review of this revision.
Herald added projects: clang, clang-tools-extra.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D157747

Files:
  clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp
  clang/include/clang/AST/Expr.h
  clang/include/clang/AST/Stmt.h
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/ASTImporter.cpp
  clang/lib/AST/Expr.cpp
  clang/lib/AST/JSONNodeDumper.cpp
  clang/lib/AST/StmtPrinter.cpp
  clang/lib/AST/TextNodeDumper.cpp
  clang/lib/CodeGen/CGExpr.cpp
  clang/lib/Lex/LiteralSupport.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/lib/Sema/SemaTemplateInstantiate.cpp
  clang/lib/Sema/TreeTransform.h
  clang/test/AST/Interp/literals.cpp
  clang/test/Sema/ms_predefined_expr.cpp

Index: clang/test/Sema/ms_predefined_expr.cpp
===
--- clang/test/Sema/ms_predefined_expr.cpp
+++ clang/test/Sema/ms_predefined_expr.cpp
@@ -1,16 +1,31 @@
-// RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-extensions
+// RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-extensions -std=c++20
 
 using size_t = __SIZE_TYPE__;
 
 // Test array initialization
 void array_init() {
- const char a[] = __FUNCTION__; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
- const char b[] = __FUNCDNAME__; // expected-warning{{initializing an array from a '__FUNCDNAME__' predefined identifier is a Microsoft extension}}
- const char c[] = __FUNCSIG__; // expected-warning{{initializing an array from a '__FUNCSIG__' predefined identifier is a Microsoft extension}}
- const char d[] = __func__; // expected-warning{{initializing an array from a '__func__' predefined identifier is a Microsoft extension}}
- const char e[] = __PRETTY_FUNCTION__; // expected-warning{{initializing an array from a '__PRETTY_FUNCTION__' predefined identifier is a Microsoft extension}}
- const wchar_t f[] = L__FUNCTION__; // expected-warning{{initializing an array from a 'L__FUNCTION__' predefined identifier is a Microsoft extension}}
- const wchar_t g[] = L__FUNCSIG__; // expected-warning{{initializing an array from a 'L__FUNCSIG__' predefined identifier is a Microsoft extension}}
+ const char a_f[] = __func__; // expected-warning{{initializing an array from a '__func__' predefined identifier is a Microsoft extension}}
+ const char a_P[] = __PRETTY_FUNCTION__; // expected-warning{{initializing an array from a '__PRETTY_FUNCTION__' predefined identifier is a Microsoft extension}}
+
+ const char a_F[] = __FUNCTION__;  // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
+ const char a_D[] = __FUNCDNAME__; // expected-warning{{initializing an array from a '__FUNCDNAME__' predefined identifier is a Microsoft extension}}
+ const char a_S[] = __FUNCSIG__;   // expected-warning{{initializing an array from a '__FUNCSIG__' predefined identifier is a Microsoft extension}}
+
+ const wchar_t L_F[] = L__FUNCTION__;  // expected-warning{{initializing an array from a 'L__FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t L_D[] = L__FUNCDNAME__; // expected-warning{{initializing an array from a 'L__FUNCDNAME__' predefined identifier is a Microsoft extension}}
+ const wchar_t L_S[] = L__FUNCSIG__;   // expected-warning{{initializing an array from a 'L__FUNCSIG__' predefined identifier is a Microsoft extension}}
+
+ const char8_t u8_F[] = u8__FUNCTION__;  // expected-warning{{initializing an array from a 'u8__FUNCTION__' predefined identifier is a Microsoft extension}}
+ const char8_t u8_D[] = u8__FUNCDNAME__; // expected-warning{{initializing an array from a 'u8__FUNCDNAME__' predefined identifier is a Microsoft extension}}
+ const char8_t u8_S[] = u8__FUNCSIG__;   // expected-warning{{initializing an array from a 'u8__FUNCSIG__' predefined identifier is a Microsoft extension}}
+
+ const char16_t u_F[] = u__FUNCTION__;  // expected-warning{{initializing an array from a 'u__FUNCTION__' predefined identifier is a Microsoft extension}}
+ const char16_t u_D[] = u__FUNCDNAME__; // expected-warning{{initializing an array from a 'u__FUNCDNAME__' predefined identifier is a Microsoft extension}}
+ const char16_t u_S[] = u__FUNCSIG__;   // expected-warning{{initializing an array from a 'u__FUNCSIG__' predefined identifier is a Microsoft extension}}
+
+ const char32_t U_F[] = U__FUNCTION__;  // expected-warning{{initializing an array from a 'U__FUNCTION__' predefined identifier is a Microsoft extension}}
+ const char32_t U_D[] = U__FUNCDNAME__; // expected-warning{{initializing an array from a 'U__FUNCDNAME__' pr

[PATCH] D157747: Support Unicode Microsoft predefined macros

2023-08-11 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added a comment.

This implementation preserves support for identifiers `L__FUNCSIG__` and 
`L__FUNCTION__` (which have never been supported by MSVC), and adds other 
identifiers for all supported encodings: L, u8, u, U.

If breaking backwards compatibility in clang (with Microsoft Extensions) is 
allowed, then I'd prefer other (more correct) solution: support for 
`__LPREFIX`-family macros ( see https://godbolt.org/z/eacYqh1ab ), and remove 
token/identifiers like `L__FUNCTION__`; relevant issue 
https://github.com/llvm/llvm-project/issues/27402
I'll try to implement this alternative approach.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157747

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


[PATCH] D153914: [clang-cl] Enable concatenation of predefined identifiers

2023-07-14 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 540395.
RIscRIpt added a comment.

Addressed review comments.

In D153914#4497696 , @aaron.ballman 
wrote:

> Sema seems like the wrong place to perform such concatenations, but given 
> that adjacent string literals are concatenated during phase 6...

I agree, but I couldn't come up with anything better (having limited knowledge 
about Clang).
Other possible //ugly// solution: make actual concatenation in 
`StringLiteralParser`, but this would require either of:

1. Pass `Decl*` into `StringLiteralParser` - this requires dependency (and 
linkage) of Lex with AST.
2. Pre-calculate function names for all possible types of tokens 
(`__FUNCTION__`, `__FUNCDNAME__`, etc.) in `ActOnStringLiteral` and pass into 
`StringLiteralParser`
3. Find other way of obtaining __current__ function name in Lex.

One may wish to expand these macros during phase (4), but these macros are 
predefined identifiers in non-MSVC compilers, and MSVC don't expand them as 
macros (`-E` compiler flag); and we don't have knowledge about AST (not to 
mention the function name) during phase (4).

In D153914#4497696 , @aaron.ballman 
wrote:

> I'm not certain it's actually observable.

I didn't understand this part.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153914

Files:
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/TokenKinds.h
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/Sema/ms_predefined_expr.cpp

Index: clang/test/Sema/ms_predefined_expr.cpp
===
--- clang/test/Sema/ms_predefined_expr.cpp
+++ clang/test/Sema/ms_predefined_expr.cpp
@@ -1,9 +1,62 @@
 // RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-extensions
 
+using size_t = __SIZE_TYPE__;
+
 void f() {
  const char a[] = __FUNCTION__; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
  const char b[] = __FUNCDNAME__; // expected-warning{{initializing an array from a '__FUNCDNAME__' predefined identifier is a Microsoft extension}}
  const char c[] = __FUNCSIG__; // expected-warning{{initializing an array from a '__FUNCSIG__' predefined identifier is a Microsoft extension}}
  const char d[] = __func__; // expected-warning{{initializing an array from a '__func__' predefined identifier is a Microsoft extension}}
  const char e[] = __PRETTY_FUNCTION__; // expected-warning{{initializing an array from a '__PRETTY_FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t f[] = L__FUNCTION__; // expected-warning{{initializing an array from a 'L__FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t g[] = L__FUNCSIG__; // expected-warning{{initializing an array from a 'L__FUNCSIG__' predefined identifier is a Microsoft extension}}
+}
+
+// Test concatenation
+
+void eat_const_char_p(const char*);
+void eat_const_wchar_p(const wchar_t*);
+
+void test_concat() {
+  eat_const_char_p("s" __FUNCTION__); // expected-warning{{concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+  eat_const_char_p("s" __FUNCDNAME__); // expected-warning{{concatenation of predefined identifier '__FUNCDNAME__' is a Microsoft extension}}
+  eat_const_char_p("s" __FUNCSIG__); // expected-warning{{concatenation of predefined identifier '__FUNCSIG__' is a Microsoft extension}}
+
+  eat_const_char_p(__FUNCTION__ "s"); // expected-warning{{concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+  eat_const_char_p(__FUNCDNAME__ "s"); // expected-warning{{concatenation of predefined identifier '__FUNCDNAME__' is a Microsoft extension}}
+  eat_const_char_p(__FUNCSIG__ "s"); // expected-warning{{concatenation of predefined identifier '__FUNCSIG__' is a Microsoft extension}}
+
+  eat_const_char_p("s" __FUNCTION__ "s"); // expected-warning{{concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+  eat_const_char_p("s" __FUNCDNAME__ "s"); // expected-warning{{concatenation of predefined identifier '__FUNCDNAME__' is a Microsoft extension}}
+  eat_const_char_p("s" __FUNCSIG__ "s"); // expected-warning{{concatenation of predefined identifier '__FUNCSIG__' is a Microsoft extension}}
+}
+
+void test_wide_concat() {
+  eat_const_wchar_p(L"s" L__FUNCTION__); // expected-warning{{concatenation of predefined identifier 'L__FUNCTION__' is a Microsoft extension}}
+  eat_const_wchar_p(L"s" L__FUNCSIG__); // expected-warning{{concatenation of predefined identifier 'L__FUNCSIG__' is a Microsoft extension}}
+
+  eat_const_wchar_p(L__FUNCTION__ L"s"); // expected-warning{{conc

[PATCH] D153914: [clang-cl] Enable concatenation of predefined identifiers

2023-07-14 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added inline comments.



Comment at: clang/include/clang/Parse/Parser.h:578-582
+  bool isTokenConcatenable() const {
+return isTokenStringLiteral() ||
+   getLangOpts().MicrosoftExt &&
+   tok::isMSPredefinedMacro(Tok.getKind());
+  }

cor3ntin wrote:
> Unless you find a better name,  I think it's preferable to keep 
> `isTokenConcatenable` and `isTokenPredefinedMsMacro` as separate functions.
> Also, this seems like a weird place to check for  `getLangOpts().MicrosoftExt`
Regarding `getLangOpts().MicrosoftExt`. If you are talking about it's presence 
in a function which name is meant to be used as a predicate, I agree. If you 
are talking about `class Parser`, then there're other places with references to 
`getLangOpts()`.

Without such function `ParseStringLiteralExpression` implementation would be 
too verbose.
Let's decide what we can do after I address other comments.

Meanwhile, I renamed it to `isTokenLikeStringLiteral()`.



Comment at: clang/lib/Parse/ParseExpr.cpp:1300
   case tok::kw___PRETTY_FUNCTION__:  // primary-expression: __P..Y_F..N__ [GNU]
-Res = Actions.ActOnPredefinedExpr(Tok.getLocation(), SavedKind);
-ConsumeToken();
+Res = ParsePredefinedExpression(true);
 break;

cor3ntin wrote:
> Can we instead, look at `NextToken()` and if next token is a StringLiteral or 
> a MS predefined extension we fallthrough?
> That would avoid having duplicated logic in `ParsePredefinedExpression` and 
> `ActOnStringLiteral` which would be a nice simplification
I thought of that, but I was afraid that playing with fallthrough wasn't 
appreciated.
Thanks, fixed.



Comment at: clang/lib/Parse/ParseExpr.cpp:3294-3298
 StringToks.push_back(Tok);
-ConsumeStringToken();
-  } while (isTokenStringLiteral());
+if (isTokenStringLiteral())
+  ConsumeStringToken();
+else
+  ConsumeToken();

cor3ntin wrote:
> I think I'd prefer `ConsumeAnyToken` with an assert that checks it's a 
> stringLiteral or a predefined ms exppression
Done. But do we really need an assertion here? We have one in the function 
preamble and strict condition in `while`.



Comment at: clang/lib/Sema/SemaExpr.cpp:1955-1991
+  // MSVC treats some of predefined identifiers (e.g. __FUNCTION__) as
+  // expandable predefined macros defined as string literals,
+  // which may be concatenated. Expand them here (in Sema),
+  // because StringLiteralParser (in Lex) doesn't have access to AST.
+  std::vector ExpandedToks;
+  if (getLangOpts().MicrosoftExt) {
+ExpandedToks = StringToks.vec();

cor3ntin wrote:
> Can we put that logic in a separate function?
Done. Tho, I couldn't make it `const` (for the same reason I couldn't make 
`getCurScopeDecl() const`). And I wasn't sure about the interface:
```
std::vector ExpandMSPredefinedMacros(ArrayRef Toks);
```
vs
```
void ExpandMSPredefinedMacros(MutableArrayRef Toks);
```



Comment at: clang/lib/Sema/SemaExpr.cpp:1964
+for (Token &Tok : ExpandedToks) {
+  if (!tok::isMSPredefinedMacro(Tok.getKind())) {
+continue;

cor3ntin wrote:
> can you assert it's a string literal otherwise?
Done.



Comment at: clang/lib/Sema/SemaExpr.cpp:1972-1987
+  SmallString<64> Str;
+  llvm::raw_svector_ostream OS(Str);
+  Token Exp;
+  Exp.startToken();
+  if (Tok.getKind() == tok::kw_L__FUNCTION__ ||
+  Tok.getKind() == tok::kw_L__FUNCSIG__) {
+OS << 'L';

cor3ntin wrote:
> I think it might be easier to create a string_literal token directly here. 
> I'm also not sure we need to use `Lexer::Stringify`
> I think it might be easier to create a string_literal token directly here.

What do you mean? Is there a function which creates Token object from 
StringRef? Or is there a way to associate string literal value with a Token 
without PP? I would like to simplify it, but I haven't found other ways of 
achieving the same result.

> I'm also not sure we need to use Lexer::Stringify

Well, as far as I can see `StringLiteralParser` expands escape sequences. So, I 
am just being too careful here.
If not using `Lexer::Stringify` do we want to assert that function name does 
not contain neither `"` not `\` (which should not happen™)?



Comment at: clang/test/Sema/ms_predefined_expr.cpp:9
  const char e[] = __PRETTY_FUNCTION__; // expected-warning{{initializing an 
array from a '__PRETTY_FUNCTION__' predefined identifier is a Microsoft 
extension}}
+ const wchar_t f[] = L__FUNCTION__; // expected-warning{{initializing an array 
from a 'L__FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t g[] = L__FUNCSIG__; // expected-warning{{initializing an array 
from a 'L__FUNCSIG__' predefined identifier is a Microsoft extension}}

cor3ntin wrote:
> do we have any tests that 

[PATCH] D153914: [clang-cl] Enable concatenation of predefined identifiers

2023-07-14 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 540427.
RIscRIpt added a comment.

Rebased onto main


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153914

Files:
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/TokenKinds.h
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/Sema/ms_predefined_expr.cpp

Index: clang/test/Sema/ms_predefined_expr.cpp
===
--- clang/test/Sema/ms_predefined_expr.cpp
+++ clang/test/Sema/ms_predefined_expr.cpp
@@ -1,9 +1,62 @@
 // RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-extensions
 
+using size_t = __SIZE_TYPE__;
+
 void f() {
  const char a[] = __FUNCTION__; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
  const char b[] = __FUNCDNAME__; // expected-warning{{initializing an array from a '__FUNCDNAME__' predefined identifier is a Microsoft extension}}
  const char c[] = __FUNCSIG__; // expected-warning{{initializing an array from a '__FUNCSIG__' predefined identifier is a Microsoft extension}}
  const char d[] = __func__; // expected-warning{{initializing an array from a '__func__' predefined identifier is a Microsoft extension}}
  const char e[] = __PRETTY_FUNCTION__; // expected-warning{{initializing an array from a '__PRETTY_FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t f[] = L__FUNCTION__; // expected-warning{{initializing an array from a 'L__FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t g[] = L__FUNCSIG__; // expected-warning{{initializing an array from a 'L__FUNCSIG__' predefined identifier is a Microsoft extension}}
+}
+
+// Test concatenation
+
+void eat_const_char_p(const char*);
+void eat_const_wchar_p(const wchar_t*);
+
+void test_concat() {
+  eat_const_char_p("s" __FUNCTION__); // expected-warning{{concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+  eat_const_char_p("s" __FUNCDNAME__); // expected-warning{{concatenation of predefined identifier '__FUNCDNAME__' is a Microsoft extension}}
+  eat_const_char_p("s" __FUNCSIG__); // expected-warning{{concatenation of predefined identifier '__FUNCSIG__' is a Microsoft extension}}
+
+  eat_const_char_p(__FUNCTION__ "s"); // expected-warning{{concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+  eat_const_char_p(__FUNCDNAME__ "s"); // expected-warning{{concatenation of predefined identifier '__FUNCDNAME__' is a Microsoft extension}}
+  eat_const_char_p(__FUNCSIG__ "s"); // expected-warning{{concatenation of predefined identifier '__FUNCSIG__' is a Microsoft extension}}
+
+  eat_const_char_p("s" __FUNCTION__ "s"); // expected-warning{{concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+  eat_const_char_p("s" __FUNCDNAME__ "s"); // expected-warning{{concatenation of predefined identifier '__FUNCDNAME__' is a Microsoft extension}}
+  eat_const_char_p("s" __FUNCSIG__ "s"); // expected-warning{{concatenation of predefined identifier '__FUNCSIG__' is a Microsoft extension}}
+}
+
+void test_wide_concat() {
+  eat_const_wchar_p(L"s" L__FUNCTION__); // expected-warning{{concatenation of predefined identifier 'L__FUNCTION__' is a Microsoft extension}}
+  eat_const_wchar_p(L"s" L__FUNCSIG__); // expected-warning{{concatenation of predefined identifier 'L__FUNCSIG__' is a Microsoft extension}}
+
+  eat_const_wchar_p(L__FUNCTION__ L"s"); // expected-warning{{concatenation of predefined identifier 'L__FUNCTION__' is a Microsoft extension}}
+  eat_const_wchar_p(L__FUNCSIG__ L"s"); // expected-warning{{concatenation of predefined identifier 'L__FUNCSIG__' is a Microsoft extension}}
+
+  eat_const_wchar_p(L"s" L__FUNCTION__ L"s"); // expected-warning{{concatenation of predefined identifier 'L__FUNCTION__' is a Microsoft extension}}
+  eat_const_wchar_p(L"s" L__FUNCSIG__ L"s"); // expected-warning{{concatenation of predefined identifier 'L__FUNCSIG__' is a Microsoft extension}}
+}
+
+const char* test_return() {
+  return __FUNCTION__ "s" __FUNCSIG__; // expected-warning{{concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}} \
+   // expected-warning{{concatenation of predefined identifier '__FUNCSIG__' is a Microsoft extension}}
+}
+
+void test_struct_init_fn() {
+  struct test_struct_init {
+const char* str;
+  } struct_init = { "struct: " __FUNCSIG__ }; // expected-warning{{concatenation of predefined identifier '__FUNCSIG__' is a Microsoft extension}}
+}
+
+constexpr size_t operator""_len(const char*, size_t len) {
+return len;
+}
+
+void test_udliteral() {
+static_assert(__FUNCTION__ ""_len == 14)

[PATCH] D153914: [clang-cl] Enable concatenation of predefined identifiers

2023-07-14 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 540600.
RIscRIpt marked 17 inline comments as done.
RIscRIpt added a comment.

Addressed review comments, rebased onto main.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153914

Files:
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/TokenKinds.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/Sema/ms_predefined_expr.cpp

Index: clang/test/Sema/ms_predefined_expr.cpp
===
--- clang/test/Sema/ms_predefined_expr.cpp
+++ clang/test/Sema/ms_predefined_expr.cpp
@@ -1,9 +1,86 @@
 // RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-extensions
 
+using size_t = __SIZE_TYPE__;
+
 void f() {
  const char a[] = __FUNCTION__; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
  const char b[] = __FUNCDNAME__; // expected-warning{{initializing an array from a '__FUNCDNAME__' predefined identifier is a Microsoft extension}}
  const char c[] = __FUNCSIG__; // expected-warning{{initializing an array from a '__FUNCSIG__' predefined identifier is a Microsoft extension}}
  const char d[] = __func__; // expected-warning{{initializing an array from a '__func__' predefined identifier is a Microsoft extension}}
  const char e[] = __PRETTY_FUNCTION__; // expected-warning{{initializing an array from a '__PRETTY_FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t f[] = L__FUNCTION__; // expected-warning{{initializing an array from a 'L__FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t g[] = L__FUNCSIG__; // expected-warning{{initializing an array from a 'L__FUNCSIG__' predefined identifier is a Microsoft extension}}
+}
+
+const char* g_function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+const char* g_function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{string literal concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+const char* g_function_rconcat = __FUNCTION__ ""; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{string literal concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+
+namespace NS
+{
+  const char* function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+  const char* function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{string literal concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+  const char* function_rconcat = __FUNCTION__ ""; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{string literal concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+
+  struct S
+  {
+static constexpr const char* function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+static constexpr const char* function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+ // expected-warning{{string literal concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+static constexpr const char* function_rconcat = __FUNCTION__ ""; // expected-warning{{predefined identifier is only valid inside function}} \
+ // expected-warning{{string literal concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+  };
+}
+
+// Test concatenation
+
+void eat_const_char_p(const char*);
+void eat_const_wchar_p(const wchar_t*);
+
+void test_concat() {
+  eat_const_char_p("s" __FUNCTION__); // expected-warning{{string literal concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+  eat_const_char_p("s" __FUNCDNAME__); // expected-warning{{string literal concatenation of predefined identifier '__FUNCDNAME__' is a Microsoft extension}}
+  eat_const_char_p("s" __FUNCSIG__); // expected-warning{{string literal concatenation of predefined identifier '__FUNCSIG__' is a Microsoft extension}}
+
+  eat_const_char_p(__FUNCTION__ "s"); // expected-warning{{string literal concatenation of predefined

[PATCH] D153914: [clang-cl] Enable concatenation of predefined identifiers

2023-07-14 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added inline comments.



Comment at: clang/include/clang/Basic/TokenKinds.h:87-93
+/// Return true if this token is a predefined macro
+/// unexpandable by MSVC preprocessor.
+inline bool isUnexpandableMsMacro(TokenKind K) {
+  return K == tok::kw___FUNCTION__ || K == tok::kw___FUNCSIG__ ||
+ K == tok::kw_L__FUNCTION__ || K == tok::kw_L__FUNCSIG__ ||
+ K == tok::kw___FUNCDNAME__;
+}

tahonermann wrote:
> 
Thanks, I like the name. But shouldn't we reflect that we are referring to only 
Microsoft (unexpandable) macros? How about `isFunctionLocalPredefinedMsMacro`?



Comment at: clang/include/clang/Parse/Parser.h:578-582
+  bool isTokenConcatenable() const {
+return isTokenStringLiteral() ||
+   getLangOpts().MicrosoftExt &&
+   tok::isMSPredefinedMacro(Tok.getKind());
+  }

tahonermann wrote:
> RIscRIpt wrote:
> > cor3ntin wrote:
> > > Unless you find a better name,  I think it's preferable to keep 
> > > `isTokenConcatenable` and `isTokenPredefinedMsMacro` as separate 
> > > functions.
> > > Also, this seems like a weird place to check for  
> > > `getLangOpts().MicrosoftExt`
> > Regarding `getLangOpts().MicrosoftExt`. If you are talking about it's 
> > presence in a function which name is meant to be used as a predicate, I 
> > agree. If you are talking about `class Parser`, then there're other places 
> > with references to `getLangOpts()`.
> > 
> > Without such function `ParseStringLiteralExpression` implementation would 
> > be too verbose.
> > Let's decide what we can do after I address other comments.
> > 
> > Meanwhile, I renamed it to `isTokenLikeStringLiteral()`.
> I suggest passing `getLangOpts()` to `isFunctionLocalPredefinedMacro` 
> (`isUnexpandableMsMacro`) and letting it determine whether the token is or is 
> not one of these special not-really-a-string-literal macro things. This will 
> facilitate additional such macros controlled by different options while also 
> colocating the option check with the related tokens.
@tahonermann, in theory it sounds good, but if I understood you correctly, the 
implementation seem weird to me:
```
inline bool isFunctionLocalPredefinedMsMacro(TokenKind K, const LangOptions& 
langOpts) {
  if (!langOpts.MicrosoftExt)
return false;
  return K == tok::kw___FUNCTION__ || K == tok::kw___FUNCSIG__ ||
 K == tok::kw_L__FUNCTION__ || K == tok::kw_L__FUNCSIG__ ||
 K == tok::kw___FUNCDNAME__;
}
```
And I would have to add `#include "LangOptions.h"` in `TokenKinds.h`.



Comment at: clang/include/clang/Parse/Parser.h:578-582
+  bool isTokenConcatenable() const {
+return isTokenStringLiteral() ||
+   getLangOpts().MicrosoftExt &&
+   tok::isMSPredefinedMacro(Tok.getKind());
+  }

RIscRIpt wrote:
> tahonermann wrote:
> > RIscRIpt wrote:
> > > cor3ntin wrote:
> > > > Unless you find a better name,  I think it's preferable to keep 
> > > > `isTokenConcatenable` and `isTokenPredefinedMsMacro` as separate 
> > > > functions.
> > > > Also, this seems like a weird place to check for  
> > > > `getLangOpts().MicrosoftExt`
> > > Regarding `getLangOpts().MicrosoftExt`. If you are talking about it's 
> > > presence in a function which name is meant to be used as a predicate, I 
> > > agree. If you are talking about `class Parser`, then there're other 
> > > places with references to `getLangOpts()`.
> > > 
> > > Without such function `ParseStringLiteralExpression` implementation would 
> > > be too verbose.
> > > Let's decide what we can do after I address other comments.
> > > 
> > > Meanwhile, I renamed it to `isTokenLikeStringLiteral()`.
> > I suggest passing `getLangOpts()` to `isFunctionLocalPredefinedMacro` 
> > (`isUnexpandableMsMacro`) and letting it determine whether the token is or 
> > is not one of these special not-really-a-string-literal macro things. This 
> > will facilitate additional such macros controlled by different options 
> > while also colocating the option check with the related tokens.
> @tahonermann, in theory it sounds good, but if I understood you correctly, 
> the implementation seem weird to me:
> ```
> inline bool isFunctionLocalPredefinedMsMacro(TokenKind K, const LangOptions& 
> langOpts) {
>   if (!langOpts.MicrosoftExt)
> return false;
>   return K == tok::kw___FUNCTION__ || K == tok::kw___FUNCSIG__ ||
>  K == tok::kw_L__FUNCTION__ || K == tok::kw_L__FUNCSIG__ ||
>  K == tok::kw___FUNCDNAME__;
> }
> ```
> And I would have to add `#include "LangOptions.h"` in `TokenKinds.h`.
If you are still concerned about usage of LangOptions in this context, and at 
the same time you are not against of having such function, I can offer the 
following alternatives:
1. Make it a local lambda function in `ParseStringLiteralExpression`
2. Make it a TU local function in `ParseExpr.cpp`

I went with (2) to do simplification of condition in switch statement b

[PATCH] D153914: [clang-cl] Enable concatenation of predefined identifiers

2023-07-15 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added inline comments.



Comment at: clang/lib/Sema/SemaExpr.cpp:1972-1987
+  SmallString<64> Str;
+  llvm::raw_svector_ostream OS(Str);
+  Token Exp;
+  Exp.startToken();
+  if (Tok.getKind() == tok::kw_L__FUNCTION__ ||
+  Tok.getKind() == tok::kw_L__FUNCSIG__) {
+OS << 'L';

cor3ntin wrote:
> RIscRIpt wrote:
> > cor3ntin wrote:
> > > I think it might be easier to create a string_literal token directly 
> > > here. I'm also not sure we need to use `Lexer::Stringify`
> > > I think it might be easier to create a string_literal token directly here.
> > 
> > What do you mean? Is there a function which creates Token object from 
> > StringRef? Or is there a way to associate string literal value with a Token 
> > without PP? I would like to simplify it, but I haven't found other ways of 
> > achieving the same result.
> > 
> > > I'm also not sure we need to use Lexer::Stringify
> > 
> > Well, as far as I can see `StringLiteralParser` expands escape sequences. 
> > So, I am just being too careful here.
> > If not using `Lexer::Stringify` do we want to assert that function name 
> > does not contain neither `"` not `\` (which should not happen™)?
> Thanks! I really would get rid of `Stringify` here - I struggle to see how a 
> function could be produced that has characters that cannot appear in an 
> identifier. even asserting isn't very useful.
Replaced `Stringify` with enclosure into raw-string-literal. Despite 
raw-string-literals are available starting from C++11, as far as I can see 
`StringLiteralParser` does not check for the standard.
Let me know, if you believe we cannot abuse this fact, and we should keep using 
`"regular string-literal"` for this purpose.



Comment at: clang/test/Sema/ms_predefined_expr.cpp:9
  const char e[] = __PRETTY_FUNCTION__; // expected-warning{{initializing an 
array from a '__PRETTY_FUNCTION__' predefined identifier is a Microsoft 
extension}}
+ const wchar_t f[] = L__FUNCTION__; // expected-warning{{initializing an array 
from a 'L__FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t g[] = L__FUNCSIG__; // expected-warning{{initializing an array 
from a 'L__FUNCSIG__' predefined identifier is a Microsoft extension}}

cor3ntin wrote:
> RIscRIpt wrote:
> > cor3ntin wrote:
> > > do we have any tests that look at the values of these things?
> > ```
> > clang/test/Analysis/eval-predefined-exprs.cpp
> > clang/test/AST/Interp/literals.cpp
> > clang/test/SemaCXX/source_location.cpp
> > clang/test/SemaCXX/predefined-expr.cpp
> > ```
> I think it's worth add a few more tests in 
> clang/test/SemaCXX/predefined-expr.cpp checking concatenations
Added tests to check values of these string literals, as well as moved 
`ms_wide_predefined_expr.cpp` tests into `ms_predefined_expr.cpp`.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153914

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


[PATCH] D153914: [clang-cl] Enable concatenation of predefined identifiers

2023-07-15 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 540741.
RIscRIpt marked 7 inline comments as done.
RIscRIpt added a comment.

Addressed review comments, rebased onto main


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153914

Files:
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/TokenKinds.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/Sema/ms_predefined_expr.cpp
  clang/test/Sema/ms_wide_predefined_expr.cpp

Index: clang/test/Sema/ms_wide_predefined_expr.cpp
===
--- clang/test/Sema/ms_wide_predefined_expr.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-// RUN: %clang_cc1 %s -fsyntax-only -Wno-unused-value -Wmicrosoft -verify -fms-extensions
-// expected-no-diagnostics
-
-// Wide character predefined identifiers
-#define _STR2WSTR(str) L##str
-#define STR2WSTR(str) _STR2WSTR(str)
-void abcdefghi12(void) {
- const wchar_t (*ss)[12] = &STR2WSTR(__FUNCTION__);
- static int arr[sizeof(STR2WSTR(__FUNCTION__))==12*sizeof(wchar_t) ? 1 : -1];
- const wchar_t (*ss2)[31] = &STR2WSTR(__FUNCSIG__);
- static int arr2[sizeof(STR2WSTR(__FUNCSIG__))==31*sizeof(wchar_t) ? 1 : -1];
-}
-
-namespace PR13206 {
-void foo(const wchar_t *);
-
-template class A {
-public:
- void method() {
-  foo(L__FUNCTION__);
- }
-};
-
-void bar() {
- A x;
- x.method();
-}
-}
Index: clang/test/Sema/ms_predefined_expr.cpp
===
--- clang/test/Sema/ms_predefined_expr.cpp
+++ clang/test/Sema/ms_predefined_expr.cpp
@@ -1,9 +1,123 @@
 // RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-extensions
 
-void f() {
+using size_t = __SIZE_TYPE__;
+
+// Test array initialization
+void array_init() {
  const char a[] = __FUNCTION__; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
  const char b[] = __FUNCDNAME__; // expected-warning{{initializing an array from a '__FUNCDNAME__' predefined identifier is a Microsoft extension}}
  const char c[] = __FUNCSIG__; // expected-warning{{initializing an array from a '__FUNCSIG__' predefined identifier is a Microsoft extension}}
  const char d[] = __func__; // expected-warning{{initializing an array from a '__func__' predefined identifier is a Microsoft extension}}
  const char e[] = __PRETTY_FUNCTION__; // expected-warning{{initializing an array from a '__PRETTY_FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t f[] = L__FUNCTION__; // expected-warning{{initializing an array from a 'L__FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t g[] = L__FUNCSIG__; // expected-warning{{initializing an array from a 'L__FUNCSIG__' predefined identifier is a Microsoft extension}}
+}
+
+// Test function local identifiers outside of a function
+const char* g_function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+const char* g_function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{string literal concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+const char* g_function_rconcat = __FUNCTION__ ""; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{string literal concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+
+namespace NS
+{
+  const char* function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+  const char* function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{string literal concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+  const char* function_rconcat = __FUNCTION__ ""; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{string literal concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+
+  struct S
+  {
+static constexpr const char* function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+static constexpr const char* function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+ // expected-warning{{string literal concatenation of predefined identifier '__FUNCTION__' is a Microsoft exten

[PATCH] D134475: [Clang] Add support for [[msvc::constexpr]] C++11 attribute

2023-07-16 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 540803.
RIscRIpt marked an inline comment as done.
RIscRIpt added a comment.

Bump

Renamed clang/test/AST/msvc-* to ms-*
Tried to improve doc note.
Rebased onto one of stable commits from main.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134475

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/include/clang/Basic/DiagnosticASTKinds.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/AST/ExprConstant.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaStmtAttr.cpp
  clang/test/AST/ms-attrs-invalid.cpp
  clang/test/AST/ms-attrs.cpp
  clang/test/AST/ms-constexpr-new.cpp
  clang/test/Misc/pragma-attribute-supported-attributes-list.test

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
@@ -84,6 +84,7 @@
 // CHECK-NEXT: LoaderUninitialized (SubjectMatchRule_variable_is_global)
 // CHECK-NEXT: Lockable (SubjectMatchRule_record)
 // CHECK-NEXT: MIGServerRoutine (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_block)
+// CHECK-NEXT: MSConstexpr (SubjectMatchRule_function)
 // CHECK-NEXT: MSStruct (SubjectMatchRule_record)
 // CHECK-NEXT: MaybeUndef (SubjectMatchRule_variable_is_parameter)
 // CHECK-NEXT: MicroMips (SubjectMatchRule_function)
Index: clang/test/AST/ms-constexpr-new.cpp
===
--- /dev/null
+++ clang/test/AST/ms-constexpr-new.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fms-extensions -std=c++20 -ast-dump %s | FileCheck %s
+
+// CHECK: used operator new
+// CHECK: MSConstexprAttr 0x{{[0-9a-f]+}} 
+[[nodiscard]] [[msvc::constexpr]] inline void* __cdecl operator new(decltype(sizeof(void*)), void* p) noexcept { return p; }
+
+// CHECK: used constexpr construct_at
+// CHECK: AttributedStmt 0x{{[0-9a-f]+}} 
+// CHECK-NEXT: MSConstexprAttr 0x{{[0-9a-f]+}} 
+// CHECK-NEXT: ReturnStmt 0x{{[0-9a-f]+}} 
+constexpr int* construct_at(int* p, int v) { [[msvc::constexpr]] return ::new (p) int(v); }
+
+constexpr bool check_construct_at() { int x; return *construct_at(&x, 42) == 42; }
+
+static_assert(check_construct_at());
Index: clang/test/AST/ms-attrs.cpp
===
--- /dev/null
+++ clang/test/AST/ms-attrs.cpp
@@ -0,0 +1,59 @@
+// RUN: %clang_cc1 -fms-extensions -std=c++20 -ast-dump %s | FileCheck %s
+
+// [[msvc::constexpr]] tests
+
+// MSConstexprDocs (1)
+// CHECK: used f1 'bool ()'
+// CHECK: MSConstexprAttr 0x{{[0-9a-f]+}} 
+[[msvc::constexpr]] bool f1() { return true; }
+
+// MSConstexprDocs (2)
+// CHECK: used constexpr f2 'bool ()'
+// CHECK: AttributedStmt 0x{{[0-9a-f]+}} 
+// CHECK-NEXT: MSConstexprAttr 0x{{[0-9a-f]+}} 
+// CHECK-NEXT: ReturnStmt 0x{{[0-9a-f]+}} 
+constexpr bool f2() { [[msvc::constexpr]] return f1(); }
+
+static_assert(f2());
+
+constexpr bool f3() { [[msvc::constexpr]] return f1() || f1() && f1(); }
+static_assert(f3());
+
+[[msvc::constexpr]] int f4(int x) { [[msvc::constexpr]] return x > 1 ? 1 + f4(x / 2) : 0; }
+constexpr bool f5() { [[msvc::constexpr]] return f4(32) == 5; }
+static_assert(f5());
+
+[[msvc::constexpr]] int f6(int x)
+{
+switch (x)
+{
+case 42: return 1337;
+default:
+ if (x < 0) [[msvc::constexpr]] return f4(-x);
+ else return x;
+}
+}
+
+constexpr bool f7() { [[msvc::constexpr]] return f6(f6(42) - 1337 + f6(-32) - 5 + (f6(1) ? f6(0) : f6(2))) == f6(0); }
+static_assert(f7());
+
+constexpr bool f8() { return true; }
+[[msvc::constexpr]] bool f9() { return f8(); }
+constexpr bool f10() { [[msvc::constexpr]] return f9(); }
+static_assert(f10());
+
+struct S1 {
+[[msvc::constexpr]] virtual bool vm() { return true; }
+constexpr bool cm() { [[msvc::constexpr]] return vm(); }
+};
+static_assert(S1{}.cm());
+
+/*
+// TODO: Add support for [[msvc::constexpr]] constructor
+struct S2 {
+[[msvc::constexpr]] S2() {}
+[[msvc::constexpr]] bool value() { return true; }
+static constexpr bool check() { [[msvc::constexpr]] return S2{}.value(); }
+};
+static_assert(S2::check());
+*/
Index: clang/test/AST/ms-attrs-invalid.cpp
===
--- /dev/null
+++ clang/test/AST/ms-attrs-invalid.cpp
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 -fms-extensions -std=c++20 -verify %s
+// RUN: %clang_cc1 -fms-extensions -std=c++17 -verify=cpp17 %s
+
+#if __cplusplus >= 202002L
+// Check explicitly invalid code
+
+void runtime() {} // expected-note {{declared here}}
+
+[[msvc::constexpr]] void f0() { runtime(); } // expected-error {{[[msvc::constexpr]] function

[PATCH] D134475: [Clang] Add support for [[msvc::constexpr]] C++11 attribute

2023-07-16 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added inline comments.



Comment at: clang/include/clang/Basic/AttrDocs.td:3543
+definition or a return statement. It has no effect on function declarations.
+This attribute permits constant evaluation of ``[[msvc::constexpr]]`` functions
+in ``[[msvc::constexpr]] return`` statements inside ``constexpr`` or

RIscRIpt wrote:
> erichkeane wrote:
> > Does it prohibit the inverse?  I think this documentation overall needs a 
> > much better description of what the semantics are here, particularly 
> > anything that you found in experimentation on the MS implementation.
> > Does it prohibit the inverse?
> Do you mean, can `[[msvc::constexpr]]` function call `constexpr` and remain 
> const-evaluated? Yes.
> 
> I elaborated on semantics in non-inline comment.
Tried to make doc notes more clear.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134475

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


[PATCH] D134475: [clang-cl] Add support for [[msvc::constexpr]] C++11 attribute

2023-07-18 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added a comment.

According to git blame @rsmith has done lots of changes in 
`clang/lib/AST/ExprConstant.cpp`; added as reviewer.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134475

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


[PATCH] D134475: [clang-cl] Add support for [[msvc::constexpr]] C++11 attribute

2023-07-19 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt marked an inline comment as done.
RIscRIpt added a comment.

Thank you for your quick response.

> Given that the intended use case is for usage behind the scenes in the 
> standard library...



> I'd strongly prefer not to have a documented, user-visible attribute that 
> gives permission to use placement new directly.

I understand your concerns, and I cannot disagree. My reasoning behind the 
current implementation is to allow clang with `-fms-extensions` to parse and 
compile the same code with the `[[msvc::constexpr]]` attribute as MSVC can. 
Given that any user of the MSVC compiler can use this attribute and compile 
their code with it, it seems to me that clang-cl should also have this 
capability. However, we don't have any guarantees that Microsoft won't modify 
anything related to this attribute. I am not aware of the policies the Clang 
project has in place for such cases. Regardless, I will adjust the patch to 
comply as necessary.

TODO for my next patch: pre-define `_MSVC_CONSTEXPR_ATTRIBUTE`




Comment at: clang/include/clang/Basic/AttrDocs.td:3609-3611
+.. Note:: To use a ``[[msvc::constexpr]]`` function in a constant context,
+   one may want to create a ``constexpr`` function-wrapper and invoke the
+   ``[[msvc::constexpr]]`` function within a ``[[msvc::constexpr]] return`` 
statement.

As per latest comments, maybe I should remove this note?



Comment at: clang/lib/AST/ExprConstant.cpp:5615-5627
+if (canEvalMSConstexpr || isMSConstexpr) {
+  // Diagnose invalid usage of [[msvc::constexpr]] function
+  bool isConstructor = isa(Definition);
+  if (canEvalMSConstexpr) { // !isMSConstexpr
+Info.FFDiag(CallLoc, diag::note_constexpr_invalid_function, 1)
+<< /*IsConstexpr*/ 0 << isConstructor << Definition;
+Info.Note(Definition->getLocation(), diag::note_declared_at);

rsmith wrote:
> Given that the intended use case is for usage behind the scenes in the 
> standard library, I don't think we should be changing our diagnostic output 
> at all here. If the library, as an implementation detail, marks a 
> non-`constexpr` function as `[[msvc::constexpr]]`, we shouldn't tell the user 
> to add `[[msvc::constexpr]]` to their code to allow it to be called, after 
> all, the annotation is an implementation detail of the MS standard library.
Sounds fair, I will adjust this code if I'm unable to convince you with my new 
comments.



Comment at: clang/lib/AST/ExprConstant.cpp:9591-9594
+  bool IsMSConstexpr = Info.CurrentCall->CanEvalMSConstexpr &&
+   OperatorNew->hasAttr();
   if (OperatorNew->isReservedGlobalPlacementOperator() &&
+  (Info.CurrentCall->isStdFunction() || IsMSConstexpr) && !E->isArray()) {

rsmith wrote:
> Do we really need this change? Was our existing check of whether the caller 
> is in namespace `std` not sufficient for MS' standard library? I'd strongly 
> prefer not to have a documented, user-visible attribute that gives permission 
> to use placement new directly.
Yes, STL's `operator new` is defined in global namespace in [[ 
https://gist.github.com/RIscRIpt/9f0991f09f97eafc375fc73ea851a81b#file-vcruntime_new-h-L165
 | vcruntime_new.h ]] (and all includes of this file are made from global 
namespace).


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134475

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


[PATCH] D153914: [clang-cl] Enable concatenation of predefined identifiers

2023-07-19 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added inline comments.



Comment at: clang/include/clang/Basic/TokenKinds.h:87-93
+/// Return true if this token is a predefined macro
+/// unexpandable by MSVC preprocessor.
+inline bool isUnexpandableMsMacro(TokenKind K) {
+  return K == tok::kw___FUNCTION__ || K == tok::kw___FUNCSIG__ ||
+ K == tok::kw_L__FUNCTION__ || K == tok::kw_L__FUNCSIG__ ||
+ K == tok::kw___FUNCDNAME__;
+}

tahonermann wrote:
> cor3ntin wrote:
> > tahonermann wrote:
> > > RIscRIpt wrote:
> > > > tahonermann wrote:
> > > > > 
> > > > Thanks, I like the name. But shouldn't we reflect that we are referring 
> > > > to only Microsoft (unexpandable) macros? How about 
> > > > `isFunctionLocalPredefinedMsMacro`?
> > > I don't think the Microsoft association is meaningful. Sure, some of the 
> > > predefined macros are only treated differently when compiling in 
> > > Microsoft mode, but some of those macros aren't Microsoft specific. Also, 
> > > there might be macros provided by other implementations that we'll want 
> > > to emulate some day.
> > I think it is, there is currently no way to link 
> > `isFunctionLocalPredefinedMacro` to the MS feature. "MSPredefinedMacro" is 
> > pretty self explanatory, same reason we most often - but not always - use 
> > GNU in the name of function related to GNU extensions.
> > There are enough similar-sounding features and extensions that we should 
> > try to make it clear which feature we are talking about.
> Perhaps we still haven't found the right name then. With the name that I've 
> been advocating, this function should also return true for 
> `tok::kw___PRETTY_FUNCTION__` even though that macro should not expand to 
> something that can be concatenated with other string literals (whether 
> compiling in Microsoft mode or not).
> 
> The Microsoft extension is the localized expansion to a string literal that 
> can be concatenated with other string literals. We probably should isolate 
> the conditions for that behavior to one place and if we do that, then I guess 
> naming this function as specific to Microsoft mode is ok; we can always 
> rename it later if it gets used for non-Microsoft extensions.
> 
> Here is my suggestion then:
>   // Return true if the token corresponds to a function local predefined
>   // macro that, in Microsoft modes, expands to a string literal (that can
>   // then be concatenated with other string literals).
>   inline bool isMsFunctionLocalStringLiteralMacro(TokenKind K, const 
> LangOptions &langOpts) {
> return langOpts.MicrosoftExt && (
> K == tok::kw___FUNCTION__ || K == tok::kw_L__FUNCTION__ ||
> K == tok::kw___FUNCSIG__ || K == tok::kw_L__FUNCSIG__ ||
> K == tok::kw___FUNCDNAME__);
>   }  
> 
> This will avoid the need for callers to check for `MicrosoftExt`; that is 
> what I really want to avoid since it is easy to forget to do that check.
1. By requiring user to pass `LangOptions` I think we can remove MS association 
(implying that there could be other non-msft cases in the future)
2. We would have to include a `LangOptions.h` in `TokenKinds.h`, are we ok with 
this? Alternatively while this function is for msft cases only, we could pass 
`bool MicrosoftExt`

Personally, I like version with `LangOptions` and removal of `MS`.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153914

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


[PATCH] D153914: [clang-cl] Enable concatenation of predefined identifiers

2023-07-20 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 542412.
RIscRIpt marked 5 inline comments as done.
RIscRIpt added a comment.

Addressed review comments, rebased onto main


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153914

Files:
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/TokenKinds.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Basic/TokenKinds.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/Sema/ms_predefined_expr.cpp
  clang/test/Sema/ms_wide_predefined_expr.cpp

Index: clang/test/Sema/ms_wide_predefined_expr.cpp
===
--- clang/test/Sema/ms_wide_predefined_expr.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-// RUN: %clang_cc1 %s -fsyntax-only -Wno-unused-value -Wmicrosoft -verify -fms-extensions
-// expected-no-diagnostics
-
-// Wide character predefined identifiers
-#define _STR2WSTR(str) L##str
-#define STR2WSTR(str) _STR2WSTR(str)
-void abcdefghi12(void) {
- const wchar_t (*ss)[12] = &STR2WSTR(__FUNCTION__);
- static int arr[sizeof(STR2WSTR(__FUNCTION__))==12*sizeof(wchar_t) ? 1 : -1];
- const wchar_t (*ss2)[31] = &STR2WSTR(__FUNCSIG__);
- static int arr2[sizeof(STR2WSTR(__FUNCSIG__))==31*sizeof(wchar_t) ? 1 : -1];
-}
-
-namespace PR13206 {
-void foo(const wchar_t *);
-
-template class A {
-public:
- void method() {
-  foo(L__FUNCTION__);
- }
-};
-
-void bar() {
- A x;
- x.method();
-}
-}
Index: clang/test/Sema/ms_predefined_expr.cpp
===
--- clang/test/Sema/ms_predefined_expr.cpp
+++ clang/test/Sema/ms_predefined_expr.cpp
@@ -1,9 +1,123 @@
 // RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-extensions
 
-void f() {
+using size_t = __SIZE_TYPE__;
+
+// Test array initialization
+void array_init() {
  const char a[] = __FUNCTION__; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
  const char b[] = __FUNCDNAME__; // expected-warning{{initializing an array from a '__FUNCDNAME__' predefined identifier is a Microsoft extension}}
  const char c[] = __FUNCSIG__; // expected-warning{{initializing an array from a '__FUNCSIG__' predefined identifier is a Microsoft extension}}
  const char d[] = __func__; // expected-warning{{initializing an array from a '__func__' predefined identifier is a Microsoft extension}}
  const char e[] = __PRETTY_FUNCTION__; // expected-warning{{initializing an array from a '__PRETTY_FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t f[] = L__FUNCTION__; // expected-warning{{initializing an array from a 'L__FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t g[] = L__FUNCSIG__; // expected-warning{{initializing an array from a 'L__FUNCSIG__' predefined identifier is a Microsoft extension}}
+}
+
+// Test function local identifiers outside of a function
+const char* g_function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+const char* g_function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{string literal concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+const char* g_function_rconcat = __FUNCTION__ ""; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{string literal concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+
+namespace NS
+{
+  const char* function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+  const char* function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{string literal concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+  const char* function_rconcat = __FUNCTION__ ""; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{string literal concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+
+  struct S
+  {
+static constexpr const char* function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+static constexpr const char* function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+ // expected-warning{{string literal concatenation of predefined identifier '_

[PATCH] D153914: [clang-cl] Enable concatenation of predefined identifiers

2023-07-20 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added inline comments.



Comment at: clang/lib/Parse/ParseExpr.cpp:1310-1311
+  case tok::kw_L__FUNCSIG__:  // primary-expression: L__FUNCSIG__ [MS]
+if (!getLangOpts().MicrosoftExt ||
+!TokenIsLikeStringLiteral(NextToken(), getLangOpts())) {
+  Res = Actions.ActOnPredefinedExpr(Tok.getLocation(), SavedKind);

tahonermann wrote:
> `TokenIsLikeStringLiteral()` checks `MicrosoftExt`, so the check here is 
> redundant. This is an example of why I would like to see the `MicrosoftExt` 
> checking pushed down to `isFunctionLocalPredefinedMsMacro()`; that really 
> seems where that checking belongs to me.
Let's consider this code:
```
if (!TokenIsLikeStringLiteral(NextToken(), getLangOpts())) {
  Res = Actions.ActOnPredefinedExpr(Tok.getLocation(), SavedKind);
  ConsumeToken();
  break;
}
```

The condition can be expanded as follows: `!(isStringLiteral || (MsExt && 
NeededToken))`. Let's consider `MsExt` is `false`, then we have: 
`!isStringLiteral`. So, if next token is StringLiteral we will try to 
concatenate it even without MsExt, which is invalid. Thus this seemingly 
redundant check is needed.



Comment at: clang/lib/Parse/ParseExpr.cpp:3298-3299
+  assert(
+  (StringToks.size() != 1 ||
+   !tok::isFunctionLocalPredefinedMsMacro(StringToks[0].getKind())) &&
+  "single predefined identifiers shall be handled by ActOnPredefinedExpr");

tahonermann wrote:
> Is there a missing check for `MicrosoftExt` here? This is another example of 
> why I would prefer to see those checks pushed down to 
> `isFunctionLocalPredefinedMsMacro()`.
My intention for this `assert` is to ensure that we keep treating single 
predefined identifiers as `PredefinedExpr` (when we don't need to concat them) 
to preserve AST. I've adjusted the check to make it more clear.



Comment at: clang/lib/Parse/ParseExpr.cpp:1300-1307
+if (!getLangOpts().MicrosoftExt || !tok::isUnexpandableMsMacro(SavedKind) 
||
+!tok::isUnexpandableMsMacro(NextToken().getKind()) &&
+!tok::isStringLiteral(NextToken().getKind())) {
+  Res = Actions.ActOnPredefinedExpr(Tok.getLocation(), SavedKind);
+  ConsumeToken();
+  break;
+}

RIscRIpt wrote:
> tahonermann wrote:
> > Since the conditional code is only relevant for some of the tokens here, I 
> > would prefer to see the other token kinds (`kw___func__`, 
> > `kw___PRETTY_FUNCTION__`) handled separately to avoid the conditional 
> > fallthrough. That means duplicating the calls to 
> > `Actions.ActOnPredefinedExpr()` and `ConsumeToken()` between the blocks, 
> > but that bothers me less than having to understand the complicated 
> > condition.
> That's a valid point. And by handling two tokens separately allows 
> simplification of the condition. Adjusted code.
Having `TokenIsLikeStringLiteral` I think we can return to single case. I 
believe 3 values in condition is not difficult.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153914

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


[PATCH] D134475: [clang-cl] Add support for [[msvc::constexpr]] C++11 attribute

2023-07-20 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 542436.
RIscRIpt marked 3 inline comments as done.
RIscRIpt added a comment.
Herald added a subscriber: MaskRay.

Addressed review comments and rebased onto main.

I have limited support of this attribute to `-fms-compatibility-version` 19.33+ 
(Visual Studio version, when this attribute first appeared).
Added definition of `_MSVC_CONSTEXPR_ATTRIBUTE`.

I am not sure whether and where to mention about adding support of this 
attribute in release notes.

Additionally, bumped `-fms-compatibility-version` to 19.33 in a separate 
commit. Although, I am not aware of all the consequences of this change.

Changed test files their names and locations.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134475

Files:
  clang/docs/ReleaseNotes.rst
  clang/docs/UsersManual.rst
  clang/lib/Driver/ToolChains/MSVC.cpp
  clang/test/Driver/cl-options.c


Index: clang/test/Driver/cl-options.c
===
--- clang/test/Driver/cl-options.c
+++ clang/test/Driver/cl-options.c
@@ -753,7 +753,7 @@
 
 // Validate that the default triple is used when run an empty tools dir is 
specified
 // RUN: %clang_cl -vctoolsdir "" -### -- %s 2>&1 | FileCheck %s --check-prefix 
VCTOOLSDIR
-// VCTOOLSDIR: "-triple" "{{[a-zA-Z0-9_-]*}}-pc-windows-msvc19.20.0"
+// VCTOOLSDIR: "-triple" "{{[a-zA-Z0-9_-]*}}-pc-windows-msvc19.33.0"
 
 // Validate that built-in include paths are based on the supplied path
 // RUN: %clang_cl --target=aarch64-pc-windows-msvc -vctoolsdir "/fake" 
-winsdkdir "/foo" -winsdkversion 10.0.12345.0 -### -- %s 2>&1 | FileCheck %s 
--check-prefix FAKEDIR
@@ -793,7 +793,7 @@
 
 // RUN: %clang_cl -vctoolsdir "" /arm64EC /c -### -- %s 2>&1 | FileCheck 
--check-prefix=ARM64EC %s 
 // ARM64EC-NOT: /arm64EC has been overridden by specified target
-// ARM64EC: "-triple" "arm64ec-pc-windows-msvc19.20.0"
+// ARM64EC: "-triple" "arm64ec-pc-windows-msvc19.33.0"
 
 // RUN: %clang_cl -vctoolsdir "" /arm64EC /c -target x86_64-pc-windows-msvc  
-### -- %s 2>&1 | FileCheck --check-prefix=ARM64EC_OVERRIDE %s
 // ARM64EC_OVERRIDE: warning: /arm64EC has been overridden by specified 
target: x86_64-pc-windows-msvc; option ignored
Index: clang/lib/Driver/ToolChains/MSVC.cpp
===
--- clang/lib/Driver/ToolChains/MSVC.cpp
+++ clang/lib/Driver/ToolChains/MSVC.cpp
@@ -787,11 +787,11 @@
   if (MSVT.empty() &&
   Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
IsWindowsMSVC)) {
-// -fms-compatibility-version=19.20 is default, aka 2019, 16.x
+// -fms-compatibility-version=19.33 is default, aka 2022, 17.3
 // NOTE: when changing this value, also update
 // clang/docs/CommandGuide/clang.rst and clang/docs/UsersManual.rst
 // accordingly.
-MSVT = VersionTuple(19, 20);
+MSVT = VersionTuple(19, 33);
   }
   return MSVT;
 }
Index: clang/docs/UsersManual.rst
===
--- clang/docs/UsersManual.rst
+++ clang/docs/UsersManual.rst
@@ -3314,8 +3314,8 @@
 
 For compatibility with existing code that compiles with MSVC, clang defines the
 ``_MSC_VER`` and ``_MSC_FULL_VER`` macros. When on Windows, these default to
-either the same value as the currently installed version of cl.exe, or ``1920``
-and ``19200`` (respectively). The ``-fms-compatibility-version=`` flag
+either the same value as the currently installed version of cl.exe, or ``1933``
+and ``19330`` (respectively). The ``-fms-compatibility-version=`` flag
 overrides these values.  It accepts a dotted version tuple, such as 
19.00.23506.
 Changing the MSVC compatibility version makes clang behave more like that
 version of MSVC. For example, ``-fms-compatibility-version=19`` will enable
Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -262,6 +262,8 @@
 - Added ``__builtin_elementwise_nearbyint`` for floating point
   types. This allows access to ``llvm.nearbyint`` for arbitrary
   floating-point and vector of floating-point types.
+- The default value of `_MSC_VER` was raised from 1920 to 1933.
+  MSVC 19.33 added undocumented attribute ``[[msvc::constexpr]]``.
 
 New Compiler Flags
 --


Index: clang/test/Driver/cl-options.c
===
--- clang/test/Driver/cl-options.c
+++ clang/test/Driver/cl-options.c
@@ -753,7 +753,7 @@
 
 // Validate that the default triple is used when run an empty tools dir is specified
 // RUN: %clang_cl -vctoolsdir "" -### -- %s 2>&1 | FileCheck %s --check-prefix VCTOOLSDIR
-// VCTOOLSDIR: "-triple" "{{[a-zA-Z0-9_-]*}}-pc-windows-msvc19.20.0"
+// VCTOOLSDIR: "-triple" "{{[a-zA-Z0-9_-]*}}-pc-windows-msvc19.33.0"
 
 /

[PATCH] D134475: [clang-cl] Add support for [[msvc::constexpr]] C++11 attribute

2023-07-20 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added inline comments.



Comment at: clang/include/clang/Basic/AttrDocs.td:3609-3611
+.. Note:: To use a ``[[msvc::constexpr]]`` function in a constant context,
+   one may want to create a ``constexpr`` function-wrapper and invoke the
+   ``[[msvc::constexpr]]`` function within a ``[[msvc::constexpr]] return`` 
statement.

RIscRIpt wrote:
> As per latest comments, maybe I should remove this note?
Removed.



Comment at: clang/include/clang/Basic/DiagnosticSemaKinds.td:2817
+  "[[msvc::constexpr]] has effect only on function definitions and return 
statements">,
+  InGroup;
 

> Given that the intended use case is for usage behind the scenes in the 
> standard library, I don't think we should be changing our diagnostic output 
> at all [there]

How about other places? Theoretically I could re-use existing warnings/errors 
with diagnostics saying `constexpr` instead of `[[msvc::constexpr]]`.



Comment at: clang/lib/AST/ExprConstant.cpp:5615-5627
+if (canEvalMSConstexpr || isMSConstexpr) {
+  // Diagnose invalid usage of [[msvc::constexpr]] function
+  bool isConstructor = isa(Definition);
+  if (canEvalMSConstexpr) { // !isMSConstexpr
+Info.FFDiag(CallLoc, diag::note_constexpr_invalid_function, 1)
+<< /*IsConstexpr*/ 0 << isConstructor << Definition;
+Info.Note(Definition->getLocation(), diag::note_declared_at);

RIscRIpt wrote:
> rsmith wrote:
> > Given that the intended use case is for usage behind the scenes in the 
> > standard library, I don't think we should be changing our diagnostic output 
> > at all here. If the library, as an implementation detail, marks a 
> > non-`constexpr` function as `[[msvc::constexpr]]`, we shouldn't tell the 
> > user to add `[[msvc::constexpr]]` to their code to allow it to be called, 
> > after all, the annotation is an implementation detail of the MS standard 
> > library.
> Sounds fair, I will adjust this code if I'm unable to convince you with my 
> new comments.
Removed, and made the check as a single `if` statement.



Comment at: clang/lib/AST/ExprConstant.cpp:9591-9594
+  bool IsMSConstexpr = Info.CurrentCall->CanEvalMSConstexpr &&
+   OperatorNew->hasAttr();
   if (OperatorNew->isReservedGlobalPlacementOperator() &&
+  (Info.CurrentCall->isStdFunction() || IsMSConstexpr) && !E->isArray()) {

rsmith wrote:
> RIscRIpt wrote:
> > rsmith wrote:
> > > Do we really need this change? Was our existing check of whether the 
> > > caller is in namespace `std` not sufficient for MS' standard library? I'd 
> > > strongly prefer not to have a documented, user-visible attribute that 
> > > gives permission to use placement new directly.
> > Yes, STL's `operator new` is defined in global namespace in [[ 
> > https://gist.github.com/RIscRIpt/9f0991f09f97eafc375fc73ea851a81b#file-vcruntime_new-h-L165
> >  | vcruntime_new.h ]] (and all includes of this file are made from global 
> > namespace).
> The existing code is checking whether the caller of `operator new` (eg, 
> `std::construct_at`) is in namespace `std`, not whether the `operator new` 
> itself is. Does MSVC's `construct_at` need this? It might if it uses a 
> placement new indirectly via a function in a different namespace, but it 
> seems likely to me that it doesn't.
Yes, sorry, my bad. This change is not needed, unless we want to support this 
attribute in user-code, which I guess we don't want to.

Removed.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134475

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


[PATCH] D134475: [clang-cl] Add support for [[msvc::constexpr]] C++11 attribute

2023-07-20 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 542438.
RIscRIpt added a comment.

add HEAD~2 patch


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134475

Files:
  clang/docs/ReleaseNotes.rst
  clang/docs/UsersManual.rst
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/LangOptions.h
  clang/lib/AST/ExprConstant.cpp
  clang/lib/Basic/Targets/OSTargets.cpp
  clang/lib/Driver/ToolChains/MSVC.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaStmtAttr.cpp
  clang/test/AST/ms-constexpr.cpp
  clang/test/Driver/cl-options.c
  clang/test/Misc/pragma-attribute-supported-attributes-list.test
  clang/test/SemaCXX/ms-constexpr-invalid.cpp
  clang/test/SemaCXX/ms-constexpr-new.cpp
  clang/test/SemaCXX/ms-constexpr.cpp

Index: clang/test/SemaCXX/ms-constexpr.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/ms-constexpr.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++20 -ast-dump -verify %s | FileCheck %s
+// expected-no-diagnostics
+
+[[msvc::constexpr]] int log2(int x) { [[msvc::constexpr]] return x > 1 ? 1 + log2(x / 2) : 0; }
+constexpr bool test_log2() { [[msvc::constexpr]] return log2(32) == 5; }
+static_assert(test_log2());
+
+[[msvc::constexpr]] int get_value(int x)
+{
+  switch (x)
+  {
+case 42: return 1337;
+default:
+ if (x < 0) [[msvc::constexpr]] return log2(-x);
+ else return x;
+  }
+}
+
+constexpr bool test_complex_expr() {
+  [[msvc::constexpr]] return get_value(get_value(42) - 1337 + get_value(-32) - 5 + (get_value(1) ? get_value(0) : get_value(2))) == get_value(0);
+}
+static_assert(test_complex_expr());
+
+constexpr bool get_constexpr_true() { return true; }
+[[msvc::constexpr]] bool get_msconstexpr_true() { return get_constexpr_true(); }
+constexpr bool test_get_msconstexpr_true() { [[msvc::constexpr]] return get_msconstexpr_true(); }
+static_assert(test_get_msconstexpr_true());
+
+/*
+// TODO: Add support for [[msvc::constexpr]] constructor
+struct S2 {
+[[msvc::constexpr]] S2() {}
+[[msvc::constexpr]] bool value() { return true; }
+static constexpr bool check() { [[msvc::constexpr]] return S2{}.value(); }
+};
+static_assert(S2::check());
+*/
Index: clang/test/SemaCXX/ms-constexpr-new.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/ms-constexpr-new.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++20 -verify=supported %s
+// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.32 -std=c++20 -verify=unsupported %s
+// supported-no-diagnostics
+
+[[nodiscard]]
+[[msvc::constexpr]] // unsupported-warning {{unknown attribute 'constexpr' ignored}}
+inline void* __cdecl operator new(decltype(sizeof(void*)), void* p) noexcept { return p; }
+
+namespace std {
+  constexpr int* construct_at(int* p, int v) {
+[[msvc::constexpr]] return ::new (p) int(v); // unsupported-warning {{unknown attribute 'constexpr' ignored}}
+  }
+}
+
+constexpr bool check_construct_at() { int x; return *std::construct_at(&x, 42) == 42; }
+static_assert(check_construct_at());
Index: clang/test/SemaCXX/ms-constexpr-invalid.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/ms-constexpr-invalid.cpp
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++20 -verify %s
+// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++17 -verify %s
+
+// Check explicitly invalid code
+
+void runtime() {} // expected-note {{declared here}}
+
+[[msvc::constexpr]] void f0() { runtime(); } // expected-error {{[[msvc::constexpr]] function never produces a constant expression}} \
+ // expected-note {{non-constexpr function 'runtime' cannot be used in a constant expression}}
+[[msvc::constexpr]] constexpr void f1() {} // expected-error {{[[msvc::constexpr]] cannot be applied to a constexpr function 'f1'}}
+#if __cplusplus >= 202202L
+[[msvc::constexpr]] consteval void f2() {} // expected-error {{[[msvc::constexpr]] cannot be applied to a consteval function 'f2'}}
+#endif
+
+struct B1 {};
+struct D1 : virtual B1 { // expected-note {{virtual base class declared here}}
+[[msvc::constexpr]] D1() {} // expected-error {{constexpr constructor not allowed in struct with virtual base class}}
+};
+
+struct [[msvc::constexpr]] S2{}; // expected-error {{'constexpr' attribute only applies to functions and statements}}
+
+// Check invalid code mixed with valid code
+
+[[msvc::constexpr]] int f4(int x) { return x > 1 ? 1 + f4(x / 2) : 0; } // expected-note {{non-constexpr

[PATCH] D134475: [clang-cl] Add support for [[msvc::constexpr]] C++11 attribute

2023-07-20 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 542441.
RIscRIpt added a comment.

Fix clang/test/SemaCXX/ms-constexpr.cpp


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134475

Files:
  clang/docs/ReleaseNotes.rst
  clang/docs/UsersManual.rst
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/LangOptions.h
  clang/lib/AST/ExprConstant.cpp
  clang/lib/Basic/Targets/OSTargets.cpp
  clang/lib/Driver/ToolChains/MSVC.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaStmtAttr.cpp
  clang/test/AST/ms-constexpr.cpp
  clang/test/Driver/cl-options.c
  clang/test/Misc/pragma-attribute-supported-attributes-list.test
  clang/test/SemaCXX/ms-constexpr-invalid.cpp
  clang/test/SemaCXX/ms-constexpr-new.cpp
  clang/test/SemaCXX/ms-constexpr.cpp

Index: clang/test/SemaCXX/ms-constexpr.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/ms-constexpr.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++20 -verify %s
+// expected-no-diagnostics
+
+[[msvc::constexpr]] int log2(int x) { [[msvc::constexpr]] return x > 1 ? 1 + log2(x / 2) : 0; }
+constexpr bool test_log2() { [[msvc::constexpr]] return log2(32) == 5; }
+static_assert(test_log2());
+
+[[msvc::constexpr]] int get_value(int x)
+{
+  switch (x)
+  {
+case 42: return 1337;
+default:
+ if (x < 0) [[msvc::constexpr]] return log2(-x);
+ else return x;
+  }
+}
+
+constexpr bool test_complex_expr() {
+  [[msvc::constexpr]] return get_value(get_value(42) - 1337 + get_value(-32) - 5 + (get_value(1) ? get_value(0) : get_value(2))) == get_value(0);
+}
+static_assert(test_complex_expr());
+
+constexpr bool get_constexpr_true() { return true; }
+[[msvc::constexpr]] bool get_msconstexpr_true() { return get_constexpr_true(); }
+constexpr bool test_get_msconstexpr_true() { [[msvc::constexpr]] return get_msconstexpr_true(); }
+static_assert(test_get_msconstexpr_true());
+
+/*
+// TODO: Add support for [[msvc::constexpr]] constructor
+struct S2 {
+[[msvc::constexpr]] S2() {}
+[[msvc::constexpr]] bool value() { return true; }
+static constexpr bool check() { [[msvc::constexpr]] return S2{}.value(); }
+};
+static_assert(S2::check());
+*/
Index: clang/test/SemaCXX/ms-constexpr-new.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/ms-constexpr-new.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++20 -verify=supported %s
+// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.32 -std=c++20 -verify=unsupported %s
+// supported-no-diagnostics
+
+[[nodiscard]]
+[[msvc::constexpr]] // unsupported-warning {{unknown attribute 'constexpr' ignored}}
+inline void* __cdecl operator new(decltype(sizeof(void*)), void* p) noexcept { return p; }
+
+namespace std {
+  constexpr int* construct_at(int* p, int v) {
+[[msvc::constexpr]] return ::new (p) int(v); // unsupported-warning {{unknown attribute 'constexpr' ignored}}
+  }
+}
+
+constexpr bool check_construct_at() { int x; return *std::construct_at(&x, 42) == 42; }
+static_assert(check_construct_at());
Index: clang/test/SemaCXX/ms-constexpr-invalid.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/ms-constexpr-invalid.cpp
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++20 -verify %s
+// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++17 -verify %s
+
+// Check explicitly invalid code
+
+void runtime() {} // expected-note {{declared here}}
+
+[[msvc::constexpr]] void f0() { runtime(); } // expected-error {{[[msvc::constexpr]] function never produces a constant expression}} \
+ // expected-note {{non-constexpr function 'runtime' cannot be used in a constant expression}}
+[[msvc::constexpr]] constexpr void f1() {} // expected-error {{[[msvc::constexpr]] cannot be applied to a constexpr function 'f1'}}
+#if __cplusplus >= 202202L
+[[msvc::constexpr]] consteval void f2() {} // expected-error {{[[msvc::constexpr]] cannot be applied to a consteval function 'f2'}}
+#endif
+
+struct B1 {};
+struct D1 : virtual B1 { // expected-note {{virtual base class declared here}}
+[[msvc::constexpr]] D1() {} // expected-error {{constexpr constructor not allowed in struct with virtual base class}}
+};
+
+struct [[msvc::constexpr]] S2{}; // expected-error {{'constexpr' attribute only applies to functions and statements}}
+
+// Check invalid code mixed with valid code
+
+[[msvc::constexpr]] int f4(int x) { return x > 1 ? 1 + f4(x / 2) : 0; } // expected-note {{non-constexpr f

[PATCH] D153914: [clang-cl] Enable concatenation of predefined identifiers

2023-07-21 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 543109.
RIscRIpt marked 5 inline comments as done.
RIscRIpt added a comment.

Address review comments, rebase onto main


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153914

Files:
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/TokenKinds.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Basic/TokenKinds.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/Sema/ms_predefined_expr.cpp
  clang/test/Sema/ms_wide_predefined_expr.cpp

Index: clang/test/Sema/ms_wide_predefined_expr.cpp
===
--- clang/test/Sema/ms_wide_predefined_expr.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-// RUN: %clang_cc1 %s -fsyntax-only -Wno-unused-value -Wmicrosoft -verify -fms-extensions
-// expected-no-diagnostics
-
-// Wide character predefined identifiers
-#define _STR2WSTR(str) L##str
-#define STR2WSTR(str) _STR2WSTR(str)
-void abcdefghi12(void) {
- const wchar_t (*ss)[12] = &STR2WSTR(__FUNCTION__);
- static int arr[sizeof(STR2WSTR(__FUNCTION__))==12*sizeof(wchar_t) ? 1 : -1];
- const wchar_t (*ss2)[31] = &STR2WSTR(__FUNCSIG__);
- static int arr2[sizeof(STR2WSTR(__FUNCSIG__))==31*sizeof(wchar_t) ? 1 : -1];
-}
-
-namespace PR13206 {
-void foo(const wchar_t *);
-
-template class A {
-public:
- void method() {
-  foo(L__FUNCTION__);
- }
-};
-
-void bar() {
- A x;
- x.method();
-}
-}
Index: clang/test/Sema/ms_predefined_expr.cpp
===
--- clang/test/Sema/ms_predefined_expr.cpp
+++ clang/test/Sema/ms_predefined_expr.cpp
@@ -1,9 +1,156 @@
 // RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-extensions
 
-void f() {
+using size_t = __SIZE_TYPE__;
+
+// Test array initialization
+void array_init() {
  const char a[] = __FUNCTION__; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
  const char b[] = __FUNCDNAME__; // expected-warning{{initializing an array from a '__FUNCDNAME__' predefined identifier is a Microsoft extension}}
  const char c[] = __FUNCSIG__; // expected-warning{{initializing an array from a '__FUNCSIG__' predefined identifier is a Microsoft extension}}
  const char d[] = __func__; // expected-warning{{initializing an array from a '__func__' predefined identifier is a Microsoft extension}}
  const char e[] = __PRETTY_FUNCTION__; // expected-warning{{initializing an array from a '__PRETTY_FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t f[] = L__FUNCTION__; // expected-warning{{initializing an array from a 'L__FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t g[] = L__FUNCSIG__; // expected-warning{{initializing an array from a 'L__FUNCSIG__' predefined identifier is a Microsoft extension}}
+}
+
+// Test function local identifiers outside of a function
+const char* g_function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+const char* g_function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{string literal concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+const char* g_function_rconcat = __FUNCTION__ ""; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{string literal concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+
+namespace NS
+{
+  const char* function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+  const char* function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{string literal concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+  const char* function_rconcat = __FUNCTION__ ""; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{string literal concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+
+  struct S
+  {
+static constexpr const char* function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+static constexpr const char* function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+ // expected-warning{{string literal concatenation of predefined identifier '__FU

[PATCH] D153914: [clang-cl] Enable concatenation of predefined identifiers

2023-07-21 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added a comment.

Thanks to your suggestion of testing different types, I realized clang does not 
support MSVC macros with `u`, `u8`, and `U` prefixes in addition to 
`L__FUNCDNAME`. By the way, clang replicates MSVC behavior a little bit 
incorrectly: `L__FUNCTION__` is not a valid token for MSVC, however it becomes 
valid if used via macro concatenation (see `#define WIDE`).
I think addition of support of new macros as well as bug fix (if possible) 
should be submitted separately. I'll open-up an issue, and submit a PR later.




Comment at: clang/lib/Sema/SemaExpr.cpp:2010-2013
+OS << "R\"EFLPM("
+   << PredefinedExpr::ComputeName(getPredefinedExprKind(Tok.getKind()),
+  currentDecl)
+   << ")EFLPM\"";

tahonermann wrote:
> "EFLPM"? I'm assuming this is an attempt to avoid an accidental clash with 
> the computed name. Does this suffice to ensure a clash can't happen? If not, 
> can we do better? Per http://eel.is/c++draft/lex.string#nt:r-char and 
> http://eel.is/c++draft/lex.charset#1, we have a lot of flexibility regarding 
> which characters to use.
At first I thought you were hinting me to use non-ascii characters for 
d-char-sequence. However, when I looked closely d-char-sequence is not as 
flexible as r-chars that you referenced: 
http://eel.is/c++draft/lex.string#nt:d-char and 
http://eel.is/c++draft/lex.charset#2

Here're my thoughts:
1. I was afraid that there could be a possibility of a function name contain 
either quote (`"`) or a backslash (`\`) despite it seemed impossible.
2. At first I used `Lexer::Stringify` to make it bullet-proof. I didn't like 
it, neither did you (reviewers).
3. I replaced `Lexer::Stringify` with raw-string-literal (d-char-sequence was 
chosen as acronym of current function name).
4. Current `EFLPM` looks weird and cryptic. And we are limited to 
[lex.charset.basic] with exceptions (space and earlier chars are not allowed). 
I think, using a raw-string-literal without d-char-sequence would be enough, 
because problem could be caused only by two consecutive characters `)"`, 
neither of which can appear in a function name.



Comment at: clang/test/Sema/ms_predefined_expr.cpp:115
+   
// expected-warning{{string literal concatenation of 
predefined identifier 'L__FUNCSIG__' is a Microsoft extension}}
+}
+

tahonermann wrote:
> How about testing some other encoding prefix combinations?
>   u"" __FUNCTION // Ok; UTF-16 string literal
>   u"" L__FUNCTION__ // ill-formed.
> 
Good idea. I am not sure whether I should specify `-std` in the test command. 
I'll leave it without, because current default standard is C++17, and I believe 
it's not going to be decreased.

And I think there are enough tests of checking values of these macros. So, in 
tests for encoding I am going to check types.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153914

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


[PATCH] D153914: [clang-cl] Enable concatenation of predefined identifiers

2023-06-27 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt created this revision.
Herald added a project: All.
RIscRIpt requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D153914

Files:
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/TokenKinds.h
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/Sema/ms_predefined_expr.cpp

Index: clang/test/Sema/ms_predefined_expr.cpp
===
--- clang/test/Sema/ms_predefined_expr.cpp
+++ clang/test/Sema/ms_predefined_expr.cpp
@@ -6,4 +6,47 @@
  const char c[] = __FUNCSIG__; // expected-warning{{initializing an array from a '__FUNCSIG__' predefined identifier is a Microsoft extension}}
  const char d[] = __func__; // expected-warning{{initializing an array from a '__func__' predefined identifier is a Microsoft extension}}
  const char e[] = __PRETTY_FUNCTION__; // expected-warning{{initializing an array from a '__PRETTY_FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t f[] = L__FUNCTION__; // expected-warning{{initializing an array from a 'L__FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t g[] = L__FUNCSIG__; // expected-warning{{initializing an array from a 'L__FUNCSIG__' predefined identifier is a Microsoft extension}}
+}
+
+// Test concatenation
+
+void eat_const_char_p(const char*);
+void eat_const_wchar_p(const wchar_t*);
+
+void test_concat() {
+  eat_const_char_p("s" __FUNCTION__); // expected-warning{{concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+  eat_const_char_p("s" __FUNCDNAME__); // expected-warning{{concatenation of predefined identifier '__FUNCDNAME__' is a Microsoft extension}}
+  eat_const_char_p("s" __FUNCSIG__); // expected-warning{{concatenation of predefined identifier '__FUNCSIG__' is a Microsoft extension}}
+
+  eat_const_char_p(__FUNCTION__ "s"); // expected-warning{{concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+  eat_const_char_p(__FUNCDNAME__ "s"); // expected-warning{{concatenation of predefined identifier '__FUNCDNAME__' is a Microsoft extension}}
+  eat_const_char_p(__FUNCSIG__ "s"); // expected-warning{{concatenation of predefined identifier '__FUNCSIG__' is a Microsoft extension}}
+
+  eat_const_char_p("s" __FUNCTION__ "s"); // expected-warning{{concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+  eat_const_char_p("s" __FUNCDNAME__ "s"); // expected-warning{{concatenation of predefined identifier '__FUNCDNAME__' is a Microsoft extension}}
+  eat_const_char_p("s" __FUNCSIG__ "s"); // expected-warning{{concatenation of predefined identifier '__FUNCSIG__' is a Microsoft extension}}
+}
+
+void test_wide_concat() {
+  eat_const_wchar_p(L"s" L__FUNCTION__); // expected-warning{{concatenation of predefined identifier 'L__FUNCTION__' is a Microsoft extension}}
+  eat_const_wchar_p(L"s" L__FUNCSIG__); // expected-warning{{concatenation of predefined identifier 'L__FUNCSIG__' is a Microsoft extension}}
+
+  eat_const_wchar_p(L__FUNCTION__ L"s"); // expected-warning{{concatenation of predefined identifier 'L__FUNCTION__' is a Microsoft extension}}
+  eat_const_wchar_p(L__FUNCSIG__ L"s"); // expected-warning{{concatenation of predefined identifier 'L__FUNCSIG__' is a Microsoft extension}}
+
+  eat_const_wchar_p(L"s" L__FUNCTION__ L"s"); // expected-warning{{concatenation of predefined identifier 'L__FUNCTION__' is a Microsoft extension}}
+  eat_const_wchar_p(L"s" L__FUNCSIG__ L"s"); // expected-warning{{concatenation of predefined identifier 'L__FUNCSIG__' is a Microsoft extension}}
+}
+
+const char* test_return() {
+  return __FUNCTION__ "s" __FUNCSIG__; // expected-warning{{concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}} \
+   // expected-warning{{concatenation of predefined identifier '__FUNCSIG__' is a Microsoft extension}}
+}
+
+void test_struct_init_fn() {
+  struct test_struct_init {
+const char* str;
+  } struct_init = { "struct: " __FUNCSIG__ }; // expected-warning{{concatenation of predefined identifier '__FUNCSIG__' is a Microsoft extension}}
 }
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -1882,6 +1882,27 @@
   ContainsUnexpandedParameterPack, ResultIndex);
 }
 
+static PredefinedExpr::IdentKind getPredefinedExprKind(tok::TokenKind Kind) {
+  switch (Kind) {
+  default:
+llvm_unreachable("unexpected TokenKind");
+  case tok::kw___func__:
+return PredefinedExpr::Func; // [C99 6.4.2.2]
+  case tok::kw___FUNCTION__:
+return PredefinedExpr::Function;
+  

[PATCH] D153914: [clang-cl] Enable concatenation of predefined identifiers

2023-06-27 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added a comment.

GitHub issue: https://github.com/llvm/llvm-project/issues/63563


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153914

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


[PATCH] D153914: [clang-cl] Enable concatenation of predefined identifiers

2023-07-07 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 538025.
RIscRIpt added a comment.

Rebased onto main


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153914

Files:
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/TokenKinds.h
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/Sema/ms_predefined_expr.cpp

Index: clang/test/Sema/ms_predefined_expr.cpp
===
--- clang/test/Sema/ms_predefined_expr.cpp
+++ clang/test/Sema/ms_predefined_expr.cpp
@@ -6,4 +6,47 @@
  const char c[] = __FUNCSIG__; // expected-warning{{initializing an array from a '__FUNCSIG__' predefined identifier is a Microsoft extension}}
  const char d[] = __func__; // expected-warning{{initializing an array from a '__func__' predefined identifier is a Microsoft extension}}
  const char e[] = __PRETTY_FUNCTION__; // expected-warning{{initializing an array from a '__PRETTY_FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t f[] = L__FUNCTION__; // expected-warning{{initializing an array from a 'L__FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t g[] = L__FUNCSIG__; // expected-warning{{initializing an array from a 'L__FUNCSIG__' predefined identifier is a Microsoft extension}}
+}
+
+// Test concatenation
+
+void eat_const_char_p(const char*);
+void eat_const_wchar_p(const wchar_t*);
+
+void test_concat() {
+  eat_const_char_p("s" __FUNCTION__); // expected-warning{{concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+  eat_const_char_p("s" __FUNCDNAME__); // expected-warning{{concatenation of predefined identifier '__FUNCDNAME__' is a Microsoft extension}}
+  eat_const_char_p("s" __FUNCSIG__); // expected-warning{{concatenation of predefined identifier '__FUNCSIG__' is a Microsoft extension}}
+
+  eat_const_char_p(__FUNCTION__ "s"); // expected-warning{{concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+  eat_const_char_p(__FUNCDNAME__ "s"); // expected-warning{{concatenation of predefined identifier '__FUNCDNAME__' is a Microsoft extension}}
+  eat_const_char_p(__FUNCSIG__ "s"); // expected-warning{{concatenation of predefined identifier '__FUNCSIG__' is a Microsoft extension}}
+
+  eat_const_char_p("s" __FUNCTION__ "s"); // expected-warning{{concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
+  eat_const_char_p("s" __FUNCDNAME__ "s"); // expected-warning{{concatenation of predefined identifier '__FUNCDNAME__' is a Microsoft extension}}
+  eat_const_char_p("s" __FUNCSIG__ "s"); // expected-warning{{concatenation of predefined identifier '__FUNCSIG__' is a Microsoft extension}}
+}
+
+void test_wide_concat() {
+  eat_const_wchar_p(L"s" L__FUNCTION__); // expected-warning{{concatenation of predefined identifier 'L__FUNCTION__' is a Microsoft extension}}
+  eat_const_wchar_p(L"s" L__FUNCSIG__); // expected-warning{{concatenation of predefined identifier 'L__FUNCSIG__' is a Microsoft extension}}
+
+  eat_const_wchar_p(L__FUNCTION__ L"s"); // expected-warning{{concatenation of predefined identifier 'L__FUNCTION__' is a Microsoft extension}}
+  eat_const_wchar_p(L__FUNCSIG__ L"s"); // expected-warning{{concatenation of predefined identifier 'L__FUNCSIG__' is a Microsoft extension}}
+
+  eat_const_wchar_p(L"s" L__FUNCTION__ L"s"); // expected-warning{{concatenation of predefined identifier 'L__FUNCTION__' is a Microsoft extension}}
+  eat_const_wchar_p(L"s" L__FUNCSIG__ L"s"); // expected-warning{{concatenation of predefined identifier 'L__FUNCSIG__' is a Microsoft extension}}
+}
+
+const char* test_return() {
+  return __FUNCTION__ "s" __FUNCSIG__; // expected-warning{{concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}} \
+   // expected-warning{{concatenation of predefined identifier '__FUNCSIG__' is a Microsoft extension}}
+}
+
+void test_struct_init_fn() {
+  struct test_struct_init {
+const char* str;
+  } struct_init = { "struct: " __FUNCSIG__ }; // expected-warning{{concatenation of predefined identifier '__FUNCSIG__' is a Microsoft extension}}
 }
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -1882,6 +1882,27 @@
   ContainsUnexpandedParameterPack, ResultIndex);
 }
 
+static PredefinedExpr::IdentKind getPredefinedExprKind(tok::TokenKind Kind) {
+  switch (Kind) {
+  default:
+llvm_unreachable("unexpected TokenKind");
+  case tok::kw___func__:
+return PredefinedExpr::Func; // [C99 6.4.2.2]
+  case tok::kw___FUNCTION__:
+return PredefinedExpr::Function;
+  case tok::kw___F

[PATCH] D134475: [Clang] Add support for [[msvc::constexpr]] C++11 attribute

2023-07-07 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 538026.
RIscRIpt added a comment.

Rebased onto main


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134475

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/include/clang/Basic/DiagnosticASTKinds.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/AST/ExprConstant.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaStmtAttr.cpp
  clang/test/AST/msvc-attrs-invalid.cpp
  clang/test/AST/msvc-attrs.cpp
  clang/test/AST/msvc-constexpr-new.cpp
  clang/test/Misc/pragma-attribute-supported-attributes-list.test

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
@@ -84,6 +84,7 @@
 // CHECK-NEXT: LoaderUninitialized (SubjectMatchRule_variable_is_global)
 // CHECK-NEXT: Lockable (SubjectMatchRule_record)
 // CHECK-NEXT: MIGServerRoutine (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_block)
+// CHECK-NEXT: MSConstexpr (SubjectMatchRule_function)
 // CHECK-NEXT: MSStruct (SubjectMatchRule_record)
 // CHECK-NEXT: MaybeUndef (SubjectMatchRule_variable_is_parameter)
 // CHECK-NEXT: MicroMips (SubjectMatchRule_function)
Index: clang/test/AST/msvc-constexpr-new.cpp
===
--- /dev/null
+++ clang/test/AST/msvc-constexpr-new.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fms-extensions -std=c++20 -ast-dump %s | FileCheck %s
+
+// CHECK: used operator new
+// CHECK: MSConstexprAttr 0x{{[0-9a-f]+}} 
+[[nodiscard]] [[msvc::constexpr]] inline void* __cdecl operator new(decltype(sizeof(void*)), void* p) noexcept { return p; }
+
+// CHECK: used constexpr construct_at
+// CHECK: AttributedStmt 0x{{[0-9a-f]+}} 
+// CHECK-NEXT: MSConstexprAttr 0x{{[0-9a-f]+}} 
+// CHECK-NEXT: ReturnStmt 0x{{[0-9a-f]+}} 
+constexpr int* construct_at(int* p, int v) { [[msvc::constexpr]] return ::new (p) int(v); }
+
+constexpr bool check_construct_at() { int x; return *construct_at(&x, 42) == 42; }
+
+static_assert(check_construct_at());
Index: clang/test/AST/msvc-attrs.cpp
===
--- /dev/null
+++ clang/test/AST/msvc-attrs.cpp
@@ -0,0 +1,59 @@
+// RUN: %clang_cc1 -fms-extensions -std=c++20 -ast-dump %s | FileCheck %s
+
+// [[msvc::constexpr]] tests
+
+// MSConstexprDocs (1)
+// CHECK: used f1 'bool ()'
+// CHECK: MSConstexprAttr 0x{{[0-9a-f]+}} 
+[[msvc::constexpr]] bool f1() { return true; }
+
+// MSConstexprDocs (2)
+// CHECK: used constexpr f2 'bool ()'
+// CHECK: AttributedStmt 0x{{[0-9a-f]+}} 
+// CHECK-NEXT: MSConstexprAttr 0x{{[0-9a-f]+}} 
+// CHECK-NEXT: ReturnStmt 0x{{[0-9a-f]+}} 
+constexpr bool f2() { [[msvc::constexpr]] return f1(); }
+
+static_assert(f2());
+
+constexpr bool f3() { [[msvc::constexpr]] return f1() || f1() && f1(); }
+static_assert(f3());
+
+[[msvc::constexpr]] int f4(int x) { [[msvc::constexpr]] return x > 1 ? 1 + f4(x / 2) : 0; }
+constexpr bool f5() { [[msvc::constexpr]] return f4(32) == 5; }
+static_assert(f5());
+
+[[msvc::constexpr]] int f6(int x)
+{
+switch (x)
+{
+case 42: return 1337;
+default:
+ if (x < 0) [[msvc::constexpr]] return f4(-x);
+ else return x;
+}
+}
+
+constexpr bool f7() { [[msvc::constexpr]] return f6(f6(42) - 1337 + f6(-32) - 5 + (f6(1) ? f6(0) : f6(2))) == f6(0); }
+static_assert(f7());
+
+constexpr bool f8() { return true; }
+[[msvc::constexpr]] bool f9() { return f8(); }
+constexpr bool f10() { [[msvc::constexpr]] return f9(); }
+static_assert(f10());
+
+struct S1 {
+[[msvc::constexpr]] virtual bool vm() { return true; }
+constexpr bool cm() { [[msvc::constexpr]] return vm(); }
+};
+static_assert(S1{}.cm());
+
+/*
+// TODO: Add support for [[msvc::constexpr]] constructor
+struct S2 {
+[[msvc::constexpr]] S2() {}
+[[msvc::constexpr]] bool value() { return true; }
+static constexpr bool check() { [[msvc::constexpr]] return S2{}.value(); }
+};
+static_assert(S2::check());
+*/
Index: clang/test/AST/msvc-attrs-invalid.cpp
===
--- /dev/null
+++ clang/test/AST/msvc-attrs-invalid.cpp
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 -fms-extensions -std=c++20 -verify %s
+// RUN: %clang_cc1 -fms-extensions -std=c++17 -verify=cpp17 %s
+
+#if __cplusplus >= 202002L
+// Check explicitly invalid code
+
+void runtime() {} // expected-note {{declared here}}
+
+[[msvc::constexpr]] void f0() { runtime(); } // expected-error {{[[msvc::constexpr]] function never produces a constant expression}} \
+ // expected-note {{non-constexpr fun

[PATCH] D153914: [clang-cl] Enable concatenation of predefined identifiers

2023-07-07 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added a comment.

Added @aaron.ballman as reviewer, because he was reviewer of related patch: 
878e590503dff 



Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153914

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


[PATCH] D134475: [clang-cl] Add support for [[msvc::constexpr]] C++11 attribute

2023-10-27 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added a comment.

Should I re-submit it to GitHub?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134475

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


[PATCH] D134475: [clang-cl] Add support for [[msvc::constexpr]] C++11 attribute

2023-10-27 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt marked an inline comment as done.
RIscRIpt added a comment.

In D134475#4655389 , @erichkeane 
wrote:

> If you can properly rebase, submit this to github, and include a summary of 
> the Phab discussion in a way that easy enough to catch back up on, I'll do a 
> deep dive into this in the next week or 3.
> Sorry for the delay, this fell off my radar somehow.

Sure, I'll try to write a summary of comments, and submit it to GitHub.
No problems regarding delays, I couldn't work at this patch in the beginning of 
this year, so it was delayed for so long.




Comment at: clang/test/SemaCXX/ms-constexpr.cpp:30
+/*
+// TODO: Add support for [[msvc::constexpr]] constructor
+struct S2 {

erichkeane wrote:
> I see this is still TODO, part of the reason I have been putting off review, 
> I thought this patch wasn't ready for review.  Whats going on here?  When is 
> this intended to be implemented?
Unfortunately, I don't think it's feasible with reasonable changes. I explained 
it in comment https://reviews.llvm.org/D134475#4288759 - search for "literal 
type".
Basically, support of `[[msvc::constexpr]]` constructors is not needed to be 
able to compile code from Microsoft's C++ Standard Library.

I think, I could create a follow up issue on GitHub, and make a reference to 
the issue here.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134475

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


[PATCH] D153914: [clang-cl] Enable concatenation of predefined identifiers

2023-07-25 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 544085.
RIscRIpt marked 6 inline comments as done.
RIscRIpt added a comment.

Addressed review comments, rebased onto main

Noticable changes:

1. Diagnostics message
2. Support of expansion of these attributes in 2nd argument of `static_assert`
3. Moved helper-functions to `Lex/LiteralSupport`
4. Changed back to usage of `Lexer::Stringify` for function name expansion

Local lit clang/test succeed for both Debug and Release builds.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153914

Files:
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/TokenKinds.h
  clang/include/clang/Lex/LiteralSupport.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Basic/TokenKinds.cpp
  clang/lib/Lex/LiteralSupport.cpp
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/Sema/ms_predefined_expr.cpp
  clang/test/Sema/ms_wide_predefined_expr.cpp

Index: clang/test/Sema/ms_wide_predefined_expr.cpp
===
--- clang/test/Sema/ms_wide_predefined_expr.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-// RUN: %clang_cc1 %s -fsyntax-only -Wno-unused-value -Wmicrosoft -verify -fms-extensions
-// expected-no-diagnostics
-
-// Wide character predefined identifiers
-#define _STR2WSTR(str) L##str
-#define STR2WSTR(str) _STR2WSTR(str)
-void abcdefghi12(void) {
- const wchar_t (*ss)[12] = &STR2WSTR(__FUNCTION__);
- static int arr[sizeof(STR2WSTR(__FUNCTION__))==12*sizeof(wchar_t) ? 1 : -1];
- const wchar_t (*ss2)[31] = &STR2WSTR(__FUNCSIG__);
- static int arr2[sizeof(STR2WSTR(__FUNCSIG__))==31*sizeof(wchar_t) ? 1 : -1];
-}
-
-namespace PR13206 {
-void foo(const wchar_t *);
-
-template class A {
-public:
- void method() {
-  foo(L__FUNCTION__);
- }
-};
-
-void bar() {
- A x;
- x.method();
-}
-}
Index: clang/test/Sema/ms_predefined_expr.cpp
===
--- clang/test/Sema/ms_predefined_expr.cpp
+++ clang/test/Sema/ms_predefined_expr.cpp
@@ -1,9 +1,170 @@
 // RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-extensions
 
-void f() {
+using size_t = __SIZE_TYPE__;
+
+// Test array initialization
+void array_init() {
  const char a[] = __FUNCTION__; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
  const char b[] = __FUNCDNAME__; // expected-warning{{initializing an array from a '__FUNCDNAME__' predefined identifier is a Microsoft extension}}
  const char c[] = __FUNCSIG__; // expected-warning{{initializing an array from a '__FUNCSIG__' predefined identifier is a Microsoft extension}}
  const char d[] = __func__; // expected-warning{{initializing an array from a '__func__' predefined identifier is a Microsoft extension}}
  const char e[] = __PRETTY_FUNCTION__; // expected-warning{{initializing an array from a '__PRETTY_FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t f[] = L__FUNCTION__; // expected-warning{{initializing an array from a 'L__FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t g[] = L__FUNCSIG__; // expected-warning{{initializing an array from a 'L__FUNCSIG__' predefined identifier is a Microsoft extension}}
+}
+
+// Test function local identifiers outside of a function
+const char* g_function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+const char* g_function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+const char* g_function_rconcat = __FUNCTION__ ""; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+
+namespace NS
+{
+  const char* function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+  const char* function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+  const char* function_rconcat = __FUNCTION__ ""; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+
+  struct S
+  {
+stat

[PATCH] D153914: [clang-cl] Enable concatenation of predefined identifiers

2023-07-25 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added inline comments.



Comment at: clang/include/clang/Basic/TokenKinds.h:87-93
+/// Return true if this token is a predefined macro
+/// unexpandable by MSVC preprocessor.
+inline bool isUnexpandableMsMacro(TokenKind K) {
+  return K == tok::kw___FUNCTION__ || K == tok::kw___FUNCSIG__ ||
+ K == tok::kw_L__FUNCTION__ || K == tok::kw_L__FUNCSIG__ ||
+ K == tok::kw___FUNCDNAME__;
+}

cor3ntin wrote:
> RIscRIpt wrote:
> > tahonermann wrote:
> > > cor3ntin wrote:
> > > > tahonermann wrote:
> > > > > RIscRIpt wrote:
> > > > > > tahonermann wrote:
> > > > > > > 
> > > > > > Thanks, I like the name. But shouldn't we reflect that we are 
> > > > > > referring to only Microsoft (unexpandable) macros? How about 
> > > > > > `isFunctionLocalPredefinedMsMacro`?
> > > > > I don't think the Microsoft association is meaningful. Sure, some of 
> > > > > the predefined macros are only treated differently when compiling in 
> > > > > Microsoft mode, but some of those macros aren't Microsoft specific. 
> > > > > Also, there might be macros provided by other implementations that 
> > > > > we'll want to emulate some day.
> > > > I think it is, there is currently no way to link 
> > > > `isFunctionLocalPredefinedMacro` to the MS feature. "MSPredefinedMacro" 
> > > > is pretty self explanatory, same reason we most often - but not always 
> > > > - use GNU in the name of function related to GNU extensions.
> > > > There are enough similar-sounding features and extensions that we 
> > > > should try to make it clear which feature we are talking about.
> > > Perhaps we still haven't found the right name then. With the name that 
> > > I've been advocating, this function should also return true for 
> > > `tok::kw___PRETTY_FUNCTION__` even though that macro should not expand to 
> > > something that can be concatenated with other string literals (whether 
> > > compiling in Microsoft mode or not).
> > > 
> > > The Microsoft extension is the localized expansion to a string literal 
> > > that can be concatenated with other string literals. We probably should 
> > > isolate the conditions for that behavior to one place and if we do that, 
> > > then I guess naming this function as specific to Microsoft mode is ok; we 
> > > can always rename it later if it gets used for non-Microsoft extensions.
> > > 
> > > Here is my suggestion then:
> > >   // Return true if the token corresponds to a function local predefined
> > >   // macro that, in Microsoft modes, expands to a string literal (that can
> > >   // then be concatenated with other string literals).
> > >   inline bool isMsFunctionLocalStringLiteralMacro(TokenKind K, const 
> > > LangOptions &langOpts) {
> > > return langOpts.MicrosoftExt && (
> > > K == tok::kw___FUNCTION__ || K == tok::kw_L__FUNCTION__ ||
> > > K == tok::kw___FUNCSIG__ || K == tok::kw_L__FUNCSIG__ ||
> > > K == tok::kw___FUNCDNAME__);
> > >   }  
> > > 
> > > This will avoid the need for callers to check for `MicrosoftExt`; that is 
> > > what I really want to avoid since it is easy to forget to do that check.
> > 1. By requiring user to pass `LangOptions` I think we can remove MS 
> > association (implying that there could be other non-msft cases in the 
> > future)
> > 2. We would have to include a `LangOptions.h` in `TokenKinds.h`, are we ok 
> > with this? Alternatively while this function is for msft cases only, we 
> > could pass `bool MicrosoftExt`
> > 
> > Personally, I like version with `LangOptions` and removal of `MS`.
> > By requiring user to pass LangOptions I think we can remove MS association
> 
> I don't think there is any motivation to future proof against hypotheticals, 
> we can always refactor later 
> 
> > We would have to include a LangOptions.h in TokenKinds.h
> 
> This makes me uneasy, but i think we can move the function to 
> `LiteralSupport.h` and include that in `ParseExpr.cpp`.
Sounds good to me. Due to other changes I also moved `TokenIsLikeStringLiteral` 
there.

> I don't think there is any motivation to future proof against hypotheticals, 
> we can always refactor later
Yes, not a strong argument, but I'd like to keep current name if you are not 
against.



Comment at: clang/lib/Sema/SemaExpr.cpp:2010-2013
+OS << "R\"EFLPM("
+   << PredefinedExpr::ComputeName(getPredefinedExprKind(Tok.getKind()),
+  currentDecl)
+   << ")EFLPM\"";

tahonermann wrote:
> cor3ntin wrote:
> > tahonermann wrote:
> > > RIscRIpt wrote:
> > > > tahonermann wrote:
> > > > > "EFLPM"? I'm assuming this is an attempt to avoid an accidental clash 
> > > > > with the computed name. Does this suffice to ensure a clash can't 
> > > > > happen? If not, can we do better? Per 
> > > > > http://eel.is/c++draft/lex.string#nt:r-char and 
> > > > > http://eel.is/c++draft/lex.charset#1, we have a lot of flexibility 
> > > > > regarding which characters t

[PATCH] D153914: [clang-cl] Enable concatenation of predefined identifiers

2023-07-25 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 544088.
RIscRIpt added a comment.

Removed irrelevant changes


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153914

Files:
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Lex/LiteralSupport.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Lex/LiteralSupport.cpp
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/Sema/ms_predefined_expr.cpp
  clang/test/Sema/ms_wide_predefined_expr.cpp

Index: clang/test/Sema/ms_wide_predefined_expr.cpp
===
--- clang/test/Sema/ms_wide_predefined_expr.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-// RUN: %clang_cc1 %s -fsyntax-only -Wno-unused-value -Wmicrosoft -verify -fms-extensions
-// expected-no-diagnostics
-
-// Wide character predefined identifiers
-#define _STR2WSTR(str) L##str
-#define STR2WSTR(str) _STR2WSTR(str)
-void abcdefghi12(void) {
- const wchar_t (*ss)[12] = &STR2WSTR(__FUNCTION__);
- static int arr[sizeof(STR2WSTR(__FUNCTION__))==12*sizeof(wchar_t) ? 1 : -1];
- const wchar_t (*ss2)[31] = &STR2WSTR(__FUNCSIG__);
- static int arr2[sizeof(STR2WSTR(__FUNCSIG__))==31*sizeof(wchar_t) ? 1 : -1];
-}
-
-namespace PR13206 {
-void foo(const wchar_t *);
-
-template class A {
-public:
- void method() {
-  foo(L__FUNCTION__);
- }
-};
-
-void bar() {
- A x;
- x.method();
-}
-}
Index: clang/test/Sema/ms_predefined_expr.cpp
===
--- clang/test/Sema/ms_predefined_expr.cpp
+++ clang/test/Sema/ms_predefined_expr.cpp
@@ -1,9 +1,170 @@
 // RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-extensions
 
-void f() {
+using size_t = __SIZE_TYPE__;
+
+// Test array initialization
+void array_init() {
  const char a[] = __FUNCTION__; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
  const char b[] = __FUNCDNAME__; // expected-warning{{initializing an array from a '__FUNCDNAME__' predefined identifier is a Microsoft extension}}
  const char c[] = __FUNCSIG__; // expected-warning{{initializing an array from a '__FUNCSIG__' predefined identifier is a Microsoft extension}}
  const char d[] = __func__; // expected-warning{{initializing an array from a '__func__' predefined identifier is a Microsoft extension}}
  const char e[] = __PRETTY_FUNCTION__; // expected-warning{{initializing an array from a '__PRETTY_FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t f[] = L__FUNCTION__; // expected-warning{{initializing an array from a 'L__FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t g[] = L__FUNCSIG__; // expected-warning{{initializing an array from a 'L__FUNCSIG__' predefined identifier is a Microsoft extension}}
+}
+
+// Test function local identifiers outside of a function
+const char* g_function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+const char* g_function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+const char* g_function_rconcat = __FUNCTION__ ""; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+
+namespace NS
+{
+  const char* function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+  const char* function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+  const char* function_rconcat = __FUNCTION__ ""; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+
+  struct S
+  {
+static constexpr const char* function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+static constexpr const char* function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+ // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a

[PATCH] D153914: [clang-cl] Enable concatenation of predefined identifiers

2023-07-25 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added inline comments.



Comment at: clang/lib/Sema/SemaExpr.cpp:1981
+  // parsed yet).
+  assert(getLangOpts().MicrosoftExt);
+

I think I should remove this assertion so this function would be usable without 
MS ext, on the other hand it would be a noop without MS ext.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153914

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


[PATCH] D153914: [clang-cl] Enable concatenation of predefined identifiers

2023-07-25 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 544114.
RIscRIpt marked 4 inline comments as done.
RIscRIpt added a comment.

Rename diagnostic messages constants


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153914

Files:
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Lex/LiteralSupport.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Lex/LiteralSupport.cpp
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/Sema/ms_predefined_expr.cpp
  clang/test/Sema/ms_wide_predefined_expr.cpp

Index: clang/test/Sema/ms_wide_predefined_expr.cpp
===
--- clang/test/Sema/ms_wide_predefined_expr.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-// RUN: %clang_cc1 %s -fsyntax-only -Wno-unused-value -Wmicrosoft -verify -fms-extensions
-// expected-no-diagnostics
-
-// Wide character predefined identifiers
-#define _STR2WSTR(str) L##str
-#define STR2WSTR(str) _STR2WSTR(str)
-void abcdefghi12(void) {
- const wchar_t (*ss)[12] = &STR2WSTR(__FUNCTION__);
- static int arr[sizeof(STR2WSTR(__FUNCTION__))==12*sizeof(wchar_t) ? 1 : -1];
- const wchar_t (*ss2)[31] = &STR2WSTR(__FUNCSIG__);
- static int arr2[sizeof(STR2WSTR(__FUNCSIG__))==31*sizeof(wchar_t) ? 1 : -1];
-}
-
-namespace PR13206 {
-void foo(const wchar_t *);
-
-template class A {
-public:
- void method() {
-  foo(L__FUNCTION__);
- }
-};
-
-void bar() {
- A x;
- x.method();
-}
-}
Index: clang/test/Sema/ms_predefined_expr.cpp
===
--- clang/test/Sema/ms_predefined_expr.cpp
+++ clang/test/Sema/ms_predefined_expr.cpp
@@ -1,9 +1,170 @@
 // RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-extensions
 
-void f() {
+using size_t = __SIZE_TYPE__;
+
+// Test array initialization
+void array_init() {
  const char a[] = __FUNCTION__; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
  const char b[] = __FUNCDNAME__; // expected-warning{{initializing an array from a '__FUNCDNAME__' predefined identifier is a Microsoft extension}}
  const char c[] = __FUNCSIG__; // expected-warning{{initializing an array from a '__FUNCSIG__' predefined identifier is a Microsoft extension}}
  const char d[] = __func__; // expected-warning{{initializing an array from a '__func__' predefined identifier is a Microsoft extension}}
  const char e[] = __PRETTY_FUNCTION__; // expected-warning{{initializing an array from a '__PRETTY_FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t f[] = L__FUNCTION__; // expected-warning{{initializing an array from a 'L__FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t g[] = L__FUNCSIG__; // expected-warning{{initializing an array from a 'L__FUNCSIG__' predefined identifier is a Microsoft extension}}
+}
+
+// Test function local identifiers outside of a function
+const char* g_function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+const char* g_function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+const char* g_function_rconcat = __FUNCTION__ ""; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+
+namespace NS
+{
+  const char* function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+  const char* function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+  const char* function_rconcat = __FUNCTION__ ""; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+
+  struct S
+  {
+static constexpr const char* function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+static constexpr const char* function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+ // expected-warning{{expansion of predefin

[PATCH] D153914: [clang-cl] Enable concatenation of predefined identifiers

2023-07-26 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 544235.
RIscRIpt marked an inline comment as done.
RIscRIpt added a comment.

Rename MicrosoftStringLiteralFromPredefined


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153914

Files:
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Lex/LiteralSupport.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Lex/LiteralSupport.cpp
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/Sema/ms_predefined_expr.cpp
  clang/test/Sema/ms_wide_predefined_expr.cpp

Index: clang/test/Sema/ms_wide_predefined_expr.cpp
===
--- clang/test/Sema/ms_wide_predefined_expr.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-// RUN: %clang_cc1 %s -fsyntax-only -Wno-unused-value -Wmicrosoft -verify -fms-extensions
-// expected-no-diagnostics
-
-// Wide character predefined identifiers
-#define _STR2WSTR(str) L##str
-#define STR2WSTR(str) _STR2WSTR(str)
-void abcdefghi12(void) {
- const wchar_t (*ss)[12] = &STR2WSTR(__FUNCTION__);
- static int arr[sizeof(STR2WSTR(__FUNCTION__))==12*sizeof(wchar_t) ? 1 : -1];
- const wchar_t (*ss2)[31] = &STR2WSTR(__FUNCSIG__);
- static int arr2[sizeof(STR2WSTR(__FUNCSIG__))==31*sizeof(wchar_t) ? 1 : -1];
-}
-
-namespace PR13206 {
-void foo(const wchar_t *);
-
-template class A {
-public:
- void method() {
-  foo(L__FUNCTION__);
- }
-};
-
-void bar() {
- A x;
- x.method();
-}
-}
Index: clang/test/Sema/ms_predefined_expr.cpp
===
--- clang/test/Sema/ms_predefined_expr.cpp
+++ clang/test/Sema/ms_predefined_expr.cpp
@@ -1,9 +1,170 @@
 // RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-extensions
 
-void f() {
+using size_t = __SIZE_TYPE__;
+
+// Test array initialization
+void array_init() {
  const char a[] = __FUNCTION__; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
  const char b[] = __FUNCDNAME__; // expected-warning{{initializing an array from a '__FUNCDNAME__' predefined identifier is a Microsoft extension}}
  const char c[] = __FUNCSIG__; // expected-warning{{initializing an array from a '__FUNCSIG__' predefined identifier is a Microsoft extension}}
  const char d[] = __func__; // expected-warning{{initializing an array from a '__func__' predefined identifier is a Microsoft extension}}
  const char e[] = __PRETTY_FUNCTION__; // expected-warning{{initializing an array from a '__PRETTY_FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t f[] = L__FUNCTION__; // expected-warning{{initializing an array from a 'L__FUNCTION__' predefined identifier is a Microsoft extension}}
+ const wchar_t g[] = L__FUNCSIG__; // expected-warning{{initializing an array from a 'L__FUNCSIG__' predefined identifier is a Microsoft extension}}
+}
+
+// Test function local identifiers outside of a function
+const char* g_function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+const char* g_function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+const char* g_function_rconcat = __FUNCTION__ ""; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+
+namespace NS
+{
+  const char* function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+  const char* function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+  const char* function_rconcat = __FUNCTION__ ""; // expected-warning{{predefined identifier is only valid inside function}} \
+  // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+
+  struct S
+  {
+static constexpr const char* function = __FUNCTION__;// expected-warning{{predefined identifier is only valid inside function}}
+static constexpr const char* function_lconcat = "" __FUNCTION__; // expected-warning{{predefined identifier is only valid inside function}} \
+ // expected-warning{{expansion of p

[PATCH] D153914: [clang-cl] Enable concatenation of predefined identifiers

2023-07-26 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added a comment.

Thank you for the review! I apologize for missing the small details; I should 
have noticed and addressed them myself.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153914

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


[PATCH] D158591: Add support of Windows Trace Logging macros

2023-08-23 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt created this revision.
Herald added a subscriber: pengfei.
Herald added a project: All.
RIscRIpt requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Consider the following code:

  #include 
  #include 
  #include 
  #include 
  
  TRACELOGGING_DEFINE_PROVIDER(
  g_hMyComponentProvider,
  "SimpleTraceLoggingProvider",
  // {0205c616-cf97-5c11-9756-56a2cee02ca7}
  (0x0205c616,0xcf97,0x5c11,0x97,0x56,0x56,0xa2,0xce,0xe0,0x2c,0xa7));
  
  void test()
  {
  TraceLoggingFunction(g_hMyComponentProvider);
  }
  
  int main()
  {
  TraceLoggingRegister(g_hMyComponentProvider);
  test();
  TraceLoggingUnregister(g_hMyComponentProvider);
  }

It compiles with MSVC, but clang-cl reports an error:

  C:\Program Files (x86)\Windows 
Kits\10\\include\10.0.22621.0\\shared/TraceLoggingActivity.h(377,30): note: 
expanded from macro '_tlgThisFunctionName'
  #define _tlgThisFunctionName __FUNCTION__
   ^
  .\tl.cpp(14,5): error: cannot initialize an array element of type 'char' with 
an lvalue of type 'const char[5]'
  TraceLoggingFunction(g_hMyComponentProvider);
  ^~~~

The second commit is not needed to support above code, however, during isolated 
tests in ms_predefined_expr.cpp
I found that MSVC accepts code with constexpr, whereas clang-cl does not.
I see that in most places PredefinedExpr is supported in constant evaluation, 
so I didn't wrap my code with ``if(MicrosoftExt)``.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D158591

Files:
  clang/lib/AST/ExprConstant.cpp
  clang/lib/Sema/Sema.cpp
  clang/test/Sema/ms_predefined_expr.cpp


Index: clang/test/Sema/ms_predefined_expr.cpp
===
--- clang/test/Sema/ms_predefined_expr.cpp
+++ clang/test/Sema/ms_predefined_expr.cpp
@@ -168,3 +168,40 @@
 void test_char_injection(decltype(sizeof('"')), decltype(sizeof("()"))) {
   unused("" __FUNCSIG__); // expected-warning{{expansion of predefined 
identifier '__FUNCSIG__' to a string literal is a Microsoft extension}}
 }
+
+void test_in_struct_init() {
+  struct {
+char F[sizeof(__FUNCTION__)];
+  } s1 = { __FUNCTION__ }; // expected-warning{{initializing an array from a 
'__FUNCTION__' predefined identifier is a Microsoft extension}}
+
+  struct {
+char F[sizeof("F:" __FUNCTION__)]; // expected-warning{{expansion of 
predefined identifier '__FUNCTION__' to a string literal is a Microsoft 
extension}}
+  } s2 = { "F:" __FUNCTION__ }; // expected-warning{{expansion of predefined 
identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+
+  class C {
+public:
+  struct {
+char F[sizeof(__FUNCTION__)];
+  } s;
+  } c1 = { { __FUNCTION__ } }; // expected-warning{{initializing an array from 
a '__FUNCTION__' predefined identifier is a Microsoft extension}}
+}
+
+void test_in_constexpr_struct_init() {
+  struct {
+char F[sizeof(__FUNCTION__)];
+  } constexpr s1 = { __FUNCTION__ }; // expected-warning{{initializing an 
array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
+  ASSERT_EQ(__FUNCTION__, s1.F);
+
+  struct {
+char F[sizeof("F:" __FUNCTION__)]; // expected-warning{{expansion of 
predefined identifier '__FUNCTION__' to a string literal is a Microsoft 
extension}}
+  } constexpr s2 = { "F:" __FUNCTION__ }; // expected-warning{{expansion of 
predefined identifier '__FUNCTION__' to a string literal is a Microsoft 
extension}}
+  ASSERT_EQ("F:" __FUNCTION__, s2.F); // expected-warning{{expansion of 
predefined identifier '__FUNCTION__' to a string literal is a Microsoft 
extension}}
+
+  class C {
+public:
+  struct {
+char F[sizeof("F:" __FUNCTION__)]; // expected-warning{{expansion of 
predefined identifier '__FUNCTION__' to a string literal is a Microsoft 
extension}}
+  } s;
+  } constexpr c1 = { { "F:" __FUNCTION__ } }; // expected-warning{{expansion 
of predefined identifier '__FUNCTION__' to a string literal is a Microsoft 
extension}}
+  ASSERT_EQ("F:" __FUNCTION__, c1.s.F); // expected-warning{{expansion of 
predefined identifier '__FUNCTION__' to a string literal is a Microsoft 
extension}}
+}
Index: clang/lib/Sema/Sema.cpp
===
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -1492,15 +1492,11 @@
 }
 
 Decl *Sema::getCurLocalScopeDecl() {
-  if (const BlockScopeInfo *BSI = getCurBlock())
-return BSI->TheDecl;
-  if (const LambdaScopeInfo *LSI = getCurLambda())
-return LSI->CallOperator;
-  if (const CapturedRegionScopeInfo *CSI = getCurCapturedRegion())
-return CSI->TheCapturedDecl;
-  if (NamedDecl *ND = getCurFunctionOrMethodDecl())
-return ND;
-  return nullptr;
+  DeclContext *DC = CurContext;
+  while (DC && !isa(DC) && !isa(DC) &&
+ !isa(DC) && !isa(DC))
+DC = DC->getPa

[PATCH] D157747: Support Unicode Microsoft predefined macros

2023-08-23 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt planned changes to this revision.
RIscRIpt added a comment.

While I work at `__LPREFIX`, I remove this revision from review queue.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157747

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


[PATCH] D158591: Add support of Windows Trace Logging macros

2023-08-23 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt marked an inline comment as done.
RIscRIpt added inline comments.



Comment at: clang/lib/Sema/Sema.cpp:1495-1499
+  DeclContext *DC = CurContext;
+  while (DC && !isa(DC) && !isa(DC) &&
+ !isa(DC) && !isa(DC))
+DC = DC->getParent();
+  return dyn_cast_or_null(DC);

cor3ntin wrote:
> I think this is reimplementing `getCurFunctionOrMethodDecl`
> maybe we want to do 
> 
> ```
> if(Decl* DC = getCurFunctionOrMethodDecl())
> return DC;
> return dyn_cast_or_null(CurrentContext);
> ```
> 
> Or something like that
Well, unfortunately, not really.

The previous implementation did call `getCurFunctionOrMethodDecl()`, but it 
returned nullptr when we were inside a RecordDecl.
If you examine the implementation of `getFunctionLevelDeclContext(bool 
AllowLambda)`, it halts if `isa(DC)`. I tried patching 
`getFunctionLevelDeclContext()` to skip RecordDecl, but this triggered around 
70 clang/tests. I didn't want to delve into understanding the failure of each 
test. If you believe there's an issue with our current code, I can allocate 
time to investigate each specific test case.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D158591

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


[PATCH] D158591: Add support of Windows Trace Logging macros

2023-08-23 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt marked 2 inline comments as done.
RIscRIpt added inline comments.



Comment at: clang/lib/Sema/Sema.cpp:1495-1499
+  DeclContext *DC = CurContext;
+  while (DC && !isa(DC) && !isa(DC) &&
+ !isa(DC) && !isa(DC))
+DC = DC->getParent();
+  return dyn_cast_or_null(DC);

cor3ntin wrote:
> RIscRIpt wrote:
> > cor3ntin wrote:
> > > I think this is reimplementing `getCurFunctionOrMethodDecl`
> > > maybe we want to do 
> > > 
> > > ```
> > > if(Decl* DC = getCurFunctionOrMethodDecl())
> > > return DC;
> > > return dyn_cast_or_null(CurrentContext);
> > > ```
> > > 
> > > Or something like that
> > Well, unfortunately, not really.
> > 
> > The previous implementation did call `getCurFunctionOrMethodDecl()`, but it 
> > returned nullptr when we were inside a RecordDecl.
> > If you examine the implementation of `getFunctionLevelDeclContext(bool 
> > AllowLambda)`, it halts if `isa(DC)`. I tried patching 
> > `getFunctionLevelDeclContext()` to skip RecordDecl, but this triggered 
> > around 70 clang/tests. I didn't want to delve into understanding the 
> > failure of each test. If you believe there's an issue with our current 
> > code, I can allocate time to investigate each specific test case.
> You are right, i missed that.
> I wish we had a better name for this function but I can't think of anything
A perfect name would be `getFunctionLevelDeclContext`, but it's taken. Welp... 
I'll try to dig-into related functions, and update when I find something. An 
alternative solution would be to parameterize (in some way) 
`getFunctionLevelDeclContext` (e.g. add bool flags, or list of skippable types, 
etc.).


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D158591

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


[PATCH] D158591: Add support of Windows Trace Logging macros

2023-08-24 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added inline comments.



Comment at: clang/lib/Sema/Sema.cpp:1495-1499
+  DeclContext *DC = CurContext;
+  while (DC && !isa(DC) && !isa(DC) &&
+ !isa(DC) && !isa(DC))
+DC = DC->getParent();
+  return dyn_cast_or_null(DC);

RIscRIpt wrote:
> cor3ntin wrote:
> > RIscRIpt wrote:
> > > cor3ntin wrote:
> > > > I think this is reimplementing `getCurFunctionOrMethodDecl`
> > > > maybe we want to do 
> > > > 
> > > > ```
> > > > if(Decl* DC = getCurFunctionOrMethodDecl())
> > > > return DC;
> > > > return dyn_cast_or_null(CurrentContext);
> > > > ```
> > > > 
> > > > Or something like that
> > > Well, unfortunately, not really.
> > > 
> > > The previous implementation did call `getCurFunctionOrMethodDecl()`, but 
> > > it returned nullptr when we were inside a RecordDecl.
> > > If you examine the implementation of `getFunctionLevelDeclContext(bool 
> > > AllowLambda)`, it halts if `isa(DC)`. I tried patching 
> > > `getFunctionLevelDeclContext()` to skip RecordDecl, but this triggered 
> > > around 70 clang/tests. I didn't want to delve into understanding the 
> > > failure of each test. If you believe there's an issue with our current 
> > > code, I can allocate time to investigate each specific test case.
> > You are right, i missed that.
> > I wish we had a better name for this function but I can't think of anything
> A perfect name would be `getFunctionLevelDeclContext`, but it's taken. 
> Welp... I'll try to dig-into related functions, and update when I find 
> something. An alternative solution would be to parameterize (in some way) 
> `getFunctionLevelDeclContext` (e.g. add bool flags, or list of skippable 
> types, etc.).
> A perfect name would be getFunctionLevelDeclContext, but it's taken. 
No, it's not. I found a better one, which was hiding in a plain sight.

Regarding using a common implementation: with a new function name it's clear 
that we cannot do that - they serve different purposes. For example, this 
function may return `BlockDecl` or `CapturedDecl` (which is accepted by 
`PredefinedExpr::ComputeName`) whereas  `getFunctionLevelDeclContext` cannot.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D158591

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


[PATCH] D158591: Add support of Windows Trace Logging macros

2023-08-24 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 553122.
RIscRIpt marked an inline comment as done.
RIscRIpt added a comment.

Rebase onto main, address review comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D158591

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/ExprConstant.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/Sema/ms_predefined_expr.cpp

Index: clang/test/Sema/ms_predefined_expr.cpp
===
--- clang/test/Sema/ms_predefined_expr.cpp
+++ clang/test/Sema/ms_predefined_expr.cpp
@@ -168,3 +168,40 @@
 void test_char_injection(decltype(sizeof('"')), decltype(sizeof("()"))) {
   unused("" __FUNCSIG__); // expected-warning{{expansion of predefined identifier '__FUNCSIG__' to a string literal is a Microsoft extension}}
 }
+
+void test_in_struct_init() {
+  struct {
+char F[sizeof(__FUNCTION__)];
+  } s1 = { __FUNCTION__ }; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
+
+  struct {
+char F[sizeof("F:" __FUNCTION__)]; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+  } s2 = { "F:" __FUNCTION__ }; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+
+  class C {
+public:
+  struct {
+char F[sizeof(__FUNCTION__)];
+  } s;
+  } c1 = { { __FUNCTION__ } }; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
+}
+
+void test_in_constexpr_struct_init() {
+  struct {
+char F[sizeof(__FUNCTION__)];
+  } constexpr s1 = { __FUNCTION__ }; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
+  ASSERT_EQ(__FUNCTION__, s1.F);
+
+  struct {
+char F[sizeof("F:" __FUNCTION__)]; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+  } constexpr s2 = { "F:" __FUNCTION__ }; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+  ASSERT_EQ("F:" __FUNCTION__, s2.F); // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+
+  class C {
+public:
+  struct {
+char F[sizeof("F:" __FUNCTION__)]; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+  } s;
+  } constexpr c1 = { { "F:" __FUNCTION__ } }; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+  ASSERT_EQ("F:" __FUNCTION__, c1.s.F); // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+}
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -1984,7 +1984,7 @@
   // Note: Although function local macros are defined only inside functions,
   // we ensure a valid `CurrentDecl` even outside of a function. This allows
   // expansion of macros into empty string literals without additional checks.
-  Decl *CurrentDecl = getCurLocalScopeDecl();
+  Decl *CurrentDecl = cast_or_null(getPredefinedExprDeclContext());
   if (!CurrentDecl)
 CurrentDecl = Context.getTranslationUnitDecl();
 
@@ -3705,7 +3705,7 @@
 
 ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
  PredefinedExpr::IdentKind IK) {
-  Decl *currentDecl = getCurLocalScopeDecl();
+  Decl *currentDecl = cast_or_null(getPredefinedExprDeclContext());
   if (!currentDecl) {
 Diag(Loc, diag::ext_predef_outside_function);
 currentDecl = Context.getTranslationUnitDecl();
Index: clang/lib/Sema/Sema.cpp
===
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -1491,16 +1491,12 @@
   return nullptr;
 }
 
-Decl *Sema::getCurLocalScopeDecl() {
-  if (const BlockScopeInfo *BSI = getCurBlock())
-return BSI->TheDecl;
-  if (const LambdaScopeInfo *LSI = getCurLambda())
-return LSI->CallOperator;
-  if (const CapturedRegionScopeInfo *CSI = getCurCapturedRegion())
-return CSI->TheCapturedDecl;
-  if (NamedDecl *ND = getCurFunctionOrMethodDecl())
-return ND;
-  return nullptr;
+DeclContext *Sema::getPredefinedExprDeclContext() {
+  DeclContext *DC = CurContext;
+  while (DC && !isa(DC) && !isa(DC) &&
+ !isa(DC) && !isa(DC))
+DC = DC->getParent();
+  return DC;
 }
 
 LangAS Sema::getDefaultCXXMethodAddrSpace() const {
Index: clang/lib/AST/ExprConstant.cpp
===
--- clang/lib/AST/Ex

[PATCH] D158591: Add support of Windows Trace Logging macros

2023-08-24 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 553123.
RIscRIpt marked an inline comment as done.
RIscRIpt added a comment.

Use isa<...> in getPredefinedExprDeclContext


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D158591

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/ExprConstant.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/Sema/ms_predefined_expr.cpp

Index: clang/test/Sema/ms_predefined_expr.cpp
===
--- clang/test/Sema/ms_predefined_expr.cpp
+++ clang/test/Sema/ms_predefined_expr.cpp
@@ -168,3 +168,40 @@
 void test_char_injection(decltype(sizeof('"')), decltype(sizeof("()"))) {
   unused("" __FUNCSIG__); // expected-warning{{expansion of predefined identifier '__FUNCSIG__' to a string literal is a Microsoft extension}}
 }
+
+void test_in_struct_init() {
+  struct {
+char F[sizeof(__FUNCTION__)];
+  } s1 = { __FUNCTION__ }; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
+
+  struct {
+char F[sizeof("F:" __FUNCTION__)]; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+  } s2 = { "F:" __FUNCTION__ }; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+
+  class C {
+public:
+  struct {
+char F[sizeof(__FUNCTION__)];
+  } s;
+  } c1 = { { __FUNCTION__ } }; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
+}
+
+void test_in_constexpr_struct_init() {
+  struct {
+char F[sizeof(__FUNCTION__)];
+  } constexpr s1 = { __FUNCTION__ }; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
+  ASSERT_EQ(__FUNCTION__, s1.F);
+
+  struct {
+char F[sizeof("F:" __FUNCTION__)]; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+  } constexpr s2 = { "F:" __FUNCTION__ }; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+  ASSERT_EQ("F:" __FUNCTION__, s2.F); // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+
+  class C {
+public:
+  struct {
+char F[sizeof("F:" __FUNCTION__)]; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+  } s;
+  } constexpr c1 = { { "F:" __FUNCTION__ } }; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+  ASSERT_EQ("F:" __FUNCTION__, c1.s.F); // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+}
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -1984,7 +1984,7 @@
   // Note: Although function local macros are defined only inside functions,
   // we ensure a valid `CurrentDecl` even outside of a function. This allows
   // expansion of macros into empty string literals without additional checks.
-  Decl *CurrentDecl = getCurLocalScopeDecl();
+  Decl *CurrentDecl = cast_or_null(getPredefinedExprDeclContext());
   if (!CurrentDecl)
 CurrentDecl = Context.getTranslationUnitDecl();
 
@@ -3705,7 +3705,7 @@
 
 ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
  PredefinedExpr::IdentKind IK) {
-  Decl *currentDecl = getCurLocalScopeDecl();
+  Decl *currentDecl = cast_or_null(getPredefinedExprDeclContext());
   if (!currentDecl) {
 Diag(Loc, diag::ext_predef_outside_function);
 currentDecl = Context.getTranslationUnitDecl();
Index: clang/lib/Sema/Sema.cpp
===
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -1491,16 +1491,11 @@
   return nullptr;
 }
 
-Decl *Sema::getCurLocalScopeDecl() {
-  if (const BlockScopeInfo *BSI = getCurBlock())
-return BSI->TheDecl;
-  if (const LambdaScopeInfo *LSI = getCurLambda())
-return LSI->CallOperator;
-  if (const CapturedRegionScopeInfo *CSI = getCurCapturedRegion())
-return CSI->TheCapturedDecl;
-  if (NamedDecl *ND = getCurFunctionOrMethodDecl())
-return ND;
-  return nullptr;
+DeclContext *Sema::getPredefinedExprDeclContext() {
+  DeclContext *DC = CurContext;
+  while (DC && !isa(DC))
+DC = DC->getParent();
+  return DC;
 }
 
 LangAS Sema::getDefaultCXXMethodAddrSpace() const {
Index: clang/lib/AST/ExprConstant.cpp
===
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConsta

[PATCH] D158591: Add support of Windows Trace Logging macros

2023-08-24 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added a comment.

I missed this comment


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D158591

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


[PATCH] D158591: Add support of Windows Trace Logging macros

2023-08-24 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added a comment.

The current implementation of `getPredefinedExprDeclContext` could be easily 
moved to a static function inside `clang/lib/Sema/SemaExpr.cpp` as it depends 
only on `Sema::CurContext` WDYT?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D158591

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


[PATCH] D158591: Add support of Windows Trace Logging macros

2023-08-25 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 553437.
RIscRIpt marked 2 inline comments as done.
RIscRIpt added a comment.

Address review comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D158591

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/ExprConstant.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/Sema/ms_predefined_expr.cpp

Index: clang/test/Sema/ms_predefined_expr.cpp
===
--- clang/test/Sema/ms_predefined_expr.cpp
+++ clang/test/Sema/ms_predefined_expr.cpp
@@ -168,3 +168,40 @@
 void test_char_injection(decltype(sizeof('"')), decltype(sizeof("()"))) {
   unused("" __FUNCSIG__); // expected-warning{{expansion of predefined identifier '__FUNCSIG__' to a string literal is a Microsoft extension}}
 }
+
+void test_in_struct_init() {
+  struct {
+char F[sizeof(__FUNCTION__)];
+  } s1 = { __FUNCTION__ }; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
+
+  struct {
+char F[sizeof("F:" __FUNCTION__)]; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+  } s2 = { "F:" __FUNCTION__ }; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+
+  class C {
+public:
+  struct {
+char F[sizeof(__FUNCTION__)];
+  } s;
+  } c1 = { { __FUNCTION__ } }; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
+}
+
+void test_in_constexpr_struct_init() {
+  struct {
+char F[sizeof(__FUNCTION__)];
+  } constexpr s1 = { __FUNCTION__ }; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
+  ASSERT_EQ(__FUNCTION__, s1.F);
+
+  struct {
+char F[sizeof("F:" __FUNCTION__)]; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+  } constexpr s2 = { "F:" __FUNCTION__ }; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+  ASSERT_EQ("F:" __FUNCTION__, s2.F); // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+
+  class C {
+public:
+  struct {
+char F[sizeof("F:" __FUNCTION__)]; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+  } s;
+  } constexpr c1 = { { "F:" __FUNCTION__ } }; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+  ASSERT_EQ("F:" __FUNCTION__, c1.s.F); // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+}
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -1904,6 +1904,16 @@
   }
 }
 
+
+/// getPredefinedExprDecl - Returns Decl of a given DeclContext that can be used
+/// to determine the value of a PredefinedExpr. This can be either a
+/// block, lambda, captured statement, function, otherwise a nullptr.
+static Decl* getPredefinedExprDecl(DeclContext *DC) {
+  while (DC && !isa(DC))
+DC = DC->getParent();
+  return cast_or_null(DC);
+}
+
 /// getUDSuffixLoc - Create a SourceLocation for a ud-suffix, given the
 /// location of the token and the offset of the ud-suffix within it.
 static SourceLocation getUDSuffixLoc(Sema &S, SourceLocation TokLoc,
@@ -1984,7 +1994,7 @@
   // Note: Although function local macros are defined only inside functions,
   // we ensure a valid `CurrentDecl` even outside of a function. This allows
   // expansion of macros into empty string literals without additional checks.
-  Decl *CurrentDecl = getCurLocalScopeDecl();
+  Decl *CurrentDecl = getPredefinedExprDecl(CurContext);
   if (!CurrentDecl)
 CurrentDecl = Context.getTranslationUnitDecl();
 
@@ -3705,7 +3715,7 @@
 
 ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
  PredefinedExpr::IdentKind IK) {
-  Decl *currentDecl = getCurLocalScopeDecl();
+  Decl *currentDecl = getPredefinedExprDecl(CurContext);
   if (!currentDecl) {
 Diag(Loc, diag::ext_predef_outside_function);
 currentDecl = Context.getTranslationUnitDecl();
Index: clang/lib/Sema/Sema.cpp
===
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -1491,18 +1491,6 @@
   return nullptr;
 }
 
-Decl *Sema::getCurLocalScopeDecl() {
-  if (const BlockScopeInfo *BSI = getCurBlock())
-return BSI->TheDecl;
-  if (const LambdaScopeInfo *LSI = getCurLambda())
-return LSI->CallOperator;
- 

[PATCH] D158591: Add support of Windows Trace Logging macros

2023-08-25 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added a comment.

Regarding new interpreter.

It takes more time and effort than I expected.
Here's what I found:

1. Assertion in ByteCodeExprGen::VisitPredefinedExpr 

 seems unnecessary.
2. StringLiteral of PredefinedExpr gets initialized in 
ByteCodeExprGen::VisitStringLiteral 
;
 I observe creation of InitMap, and initialization of each element of array.
3. However when I am at the following call-stack (just before exiting constexpr 
interpreter and doing final checks):

  00 0066`04580990 7ff6`55fb7257 
clang!clang::interp::CheckArrayInitialized+0x257 
[C:\projects\my-llvm\clang\lib\AST\Interp\Interp.cpp @ 425] 
  01 0066`04580b50 7ff6`55f67ae6 
clang!clang::interp::CheckCtorCall+0xc7 
[C:\projects\my-llvm\clang\lib\AST\Interp\Interp.cpp @ 476] 
  02 0066`04580bb0 7ff6`55ebdd17 
clang!clang::interp::CheckGlobalCtor+0x36 
[C:\projects\my-llvm\clang\lib\AST\Interp\Interp.h @ 1681] 
  03 0066`04580bf0 7ff6`55fb3e3d 
clang!clang::interp::EvalEmitter::emitCheckGlobalCtor+0x57 
[C:\projects\my-llvm\build\tools\clang\lib\AST\Opcodes.inc @ 4133] 
  04 0066`04580c20 7ff6`55fb4db1 
clang!clang::interp::ByteCodeExprGen::visitGlobalInitializer+0xdd
 [C:\projects\my-llvm\clang\lib\AST\Interp\ByteCodeExprGen.h @ 180] 
  05 0066`04580c90 7ff6`55fb33ce 
clang!clang::interp::ByteCodeExprGen::visitVarDecl+0x291
 [C:\projects\my-llvm\clang\lib\AST\Interp\ByteCodeExprGen.cpp @ 1827] 
  06 0066`04580e40 7ff6`55eb7023 
clang!clang::interp::ByteCodeExprGen::visitDecl+0x8e
 [C:\projects\my-llvm\clang\lib\AST\Interp\ByteCodeExprGen.cpp @ 1772] 
  07 0066`04580f30 7ff6`55d18d54 
clang!clang::interp::EvalEmitter::interpretDecl+0x33 
[C:\projects\my-llvm\clang\lib\AST\Interp\EvalEmitter.cpp @ 39] 
  08 0066`04580f90 7ff6`55633abf 
clang!clang::interp::Context::evaluateAsInitializer+0xf4 
[C:\projects\my-llvm\clang\lib\AST\Interp\Context.cpp @ 74] 
  09 0066`04581290 7ff6`553b4398 
clang!clang::Expr::EvaluateAsInitializer+0x28f 
[C:\projects\my-llvm\clang\lib\AST\ExprConstant.cpp @ 15545] 
  0a 0066`04581880 7ff6`553b4744 
clang!clang::VarDecl::evaluateValueImpl+0x148 
[C:\projects\my-llvm\clang\lib\AST\Decl.cpp @ 2555] 
  0b 0066`04581940 7ff6`537e94fc 
clang!clang::VarDecl::checkForConstantInitialization+0xe4 
[C:\projects\my-llvm\clang\lib\AST\Decl.cpp @ 2625] 
  0c 0066`04581980 7ff6`537f8109 
clang!clang::Sema::CheckCompleteVariableDeclaration+0xddc 
[C:\projects\my-llvm\clang\lib\Sema\SemaDecl.cpp @ 14315] 
  0d 0066`04582770 ` 
clang!clang::Sema::AddInitializerToDecl+0x2669 
[C:\projects\my-llvm\clang\lib\Sema\SemaDecl.cpp @ 13712] 

In CheckArrayInitialized 

 `BasePtr.atIndex(I).isInitialized()` returns false, because InitMap does not 
exist. And it seems that `BasePtr` points to a different object, not the one 
which corresponds to StringLiteral (at step 2). This new interpreter does not 
use clang's AST, so it becomes difficult to understand what's happening. Any 
help would be appreciated. cc @tbaeder.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D158591

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


[PATCH] D158591: Add support of Windows Trace Logging macros

2023-08-25 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added a comment.

In D158591#4616728 , @RIscRIpt wrote:

> And it seems that `BasePtr` points to a different object, not the one which 
> corresponds to StringLiteral (at step 2).

If I understand everything correctly, then in visitGlobalInitializer 
,
 when we return from `visitInitializer` our `this->Locals` becomes empty. So 
`this->emitCheckGlobalCtor(Init)` fails, because it sees are elements are 
uninitialized.

Thanks for approval! Let me know if I should report my observations about new 
constexpr interpreter somewhere else.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D158591

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


[PATCH] D158591: Add support of Windows Trace Logging macros

2023-08-25 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 553444.
RIscRIpt added a comment.

Rebased onto main, fixed commit messages, fixed formatting, re-run lit for 
clang/test


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D158591

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/ExprConstant.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/Sema/ms_predefined_expr.cpp

Index: clang/test/Sema/ms_predefined_expr.cpp
===
--- clang/test/Sema/ms_predefined_expr.cpp
+++ clang/test/Sema/ms_predefined_expr.cpp
@@ -168,3 +168,40 @@
 void test_char_injection(decltype(sizeof('"')), decltype(sizeof("()"))) {
   unused("" __FUNCSIG__); // expected-warning{{expansion of predefined identifier '__FUNCSIG__' to a string literal is a Microsoft extension}}
 }
+
+void test_in_struct_init() {
+  struct {
+char F[sizeof(__FUNCTION__)];
+  } s1 = { __FUNCTION__ }; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
+
+  struct {
+char F[sizeof("F:" __FUNCTION__)]; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+  } s2 = { "F:" __FUNCTION__ }; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+
+  class C {
+public:
+  struct {
+char F[sizeof(__FUNCTION__)];
+  } s;
+  } c1 = { { __FUNCTION__ } }; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
+}
+
+void test_in_constexpr_struct_init() {
+  struct {
+char F[sizeof(__FUNCTION__)];
+  } constexpr s1 = { __FUNCTION__ }; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
+  ASSERT_EQ(__FUNCTION__, s1.F);
+
+  struct {
+char F[sizeof("F:" __FUNCTION__)]; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+  } constexpr s2 = { "F:" __FUNCTION__ }; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+  ASSERT_EQ("F:" __FUNCTION__, s2.F); // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+
+  class C {
+public:
+  struct {
+char F[sizeof("F:" __FUNCTION__)]; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+  } s;
+  } constexpr c1 = { { "F:" __FUNCTION__ } }; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+  ASSERT_EQ("F:" __FUNCTION__, c1.s.F); // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
+}
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -1904,6 +1904,15 @@
   }
 }
 
+/// getPredefinedExprDecl - Returns Decl of a given DeclContext that can be used
+/// to determine the value of a PredefinedExpr. This can be either a
+/// block, lambda, captured statement, function, otherwise a nullptr.
+static Decl *getPredefinedExprDecl(DeclContext *DC) {
+  while (DC && !isa(DC))
+DC = DC->getParent();
+  return cast_or_null(DC);
+}
+
 /// getUDSuffixLoc - Create a SourceLocation for a ud-suffix, given the
 /// location of the token and the offset of the ud-suffix within it.
 static SourceLocation getUDSuffixLoc(Sema &S, SourceLocation TokLoc,
@@ -1984,7 +1993,7 @@
   // Note: Although function local macros are defined only inside functions,
   // we ensure a valid `CurrentDecl` even outside of a function. This allows
   // expansion of macros into empty string literals without additional checks.
-  Decl *CurrentDecl = getCurLocalScopeDecl();
+  Decl *CurrentDecl = getPredefinedExprDecl(CurContext);
   if (!CurrentDecl)
 CurrentDecl = Context.getTranslationUnitDecl();
 
@@ -3705,7 +3714,7 @@
 
 ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
  PredefinedExpr::IdentKind IK) {
-  Decl *currentDecl = getCurLocalScopeDecl();
+  Decl *currentDecl = getPredefinedExprDecl(CurContext);
   if (!currentDecl) {
 Diag(Loc, diag::ext_predef_outside_function);
 currentDecl = Context.getTranslationUnitDecl();
Index: clang/lib/Sema/Sema.cpp
===
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -1491,18 +1491,6 @@
   return nullptr;
 }
 
-Decl *Sema::getCurLocalScopeDecl() {
-  if (const BlockScopeInfo *BSI = getCurBlock())
-return BSI->TheDecl;
-  if (const LambdaScopeInfo *LSI = getCurLambda())
-return LSI

[PATCH] D157747: Support Unicode Microsoft predefined macros

2023-08-31 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt abandoned this revision.
RIscRIpt added a comment.

I found a way to implement `__LPREFIX`-macros-family in Clang. I need some more 
time to finish and polish it. Going to post it a couple of weeks later.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157747

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


[PATCH] D158591: Add support of Windows Trace Logging macros

2023-09-04 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added a comment.

@cor3ntin, thanks for asking. No, I do not have access. Please merge. Commits 
should have correct email and name.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D158591

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


[PATCH] D158591: Add support of Windows Trace Logging macros

2023-09-04 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added a comment.

In D158591#4636814 , @cor3ntin wrote:

> Hum. before I do
>
> - I think the commit message could be more explicit as to what the patch does 
> ("Add support of Windows Trace Logging macros" is a bit vague)
> - Do we need a release note ?

I agree that single commit message is vague. That's why I submitted two 
separate commits with detailed messages (the first one has some details in 
body).

I don't think we need release notes, because it's a bug fix.

P.S. I don't have access to PC until next week, I am okay if you adjust commit 
messages in a way you want.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D158591

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


[PATCH] D158591: Add support of Windows Trace Logging macros

2023-09-04 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added a comment.

Looks good. Thanks!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D158591

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


[PATCH] D134475: Add C++11 attribute msvc::constexpr

2023-01-21 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added a comment.

I asked MSFT 

 to comment, let's see if they can share the spec for this attribute.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134475

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


[PATCH] D134475: [Clang] Add support for [[msvc::constexpr]] C++11 attribute

2023-06-03 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 528112.
RIscRIpt added a comment.

Added diagnostics for [[msvc::constexpr]] virtual

Regarding [[msvc::constexpr]] constructors, unfortunatelly I cannot find a 
reasonable way to support it.

During development I found out about Clang's experimental Constant Interpreter 
(`-fexperimental-new-constant-interpreter`),
I suppose it would be much easier to implement complete support for 
`[[msvc::constexpr]]` there.
I am not aware about policy regarding constant evaulation/interpreter:
do you approve new constant evaluation features in the current (AST-based) 
approach without extending the experimental one?
Because I'd rather tacke with experimental Constant Interpreter in a follow-up 
(if I ever find time for this).


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134475

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/include/clang/Basic/DiagnosticASTKinds.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/AST/ExprConstant.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaStmtAttr.cpp
  clang/test/AST/msvc-attrs-invalid.cpp
  clang/test/AST/msvc-attrs.cpp
  clang/test/AST/msvc-constexpr-new.cpp
  clang/test/Misc/pragma-attribute-supported-attributes-list.test

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
@@ -83,6 +83,7 @@
 // CHECK-NEXT: LoaderUninitialized (SubjectMatchRule_variable_is_global)
 // CHECK-NEXT: Lockable (SubjectMatchRule_record)
 // CHECK-NEXT: MIGServerRoutine (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_block)
+// CHECK-NEXT: MSConstexpr (SubjectMatchRule_function)
 // CHECK-NEXT: MSStruct (SubjectMatchRule_record)
 // CHECK-NEXT: MaybeUndef (SubjectMatchRule_variable_is_parameter)
 // CHECK-NEXT: MicroMips (SubjectMatchRule_function)
Index: clang/test/AST/msvc-constexpr-new.cpp
===
--- /dev/null
+++ clang/test/AST/msvc-constexpr-new.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fms-extensions -std=c++20 -ast-dump %s | FileCheck %s
+
+// CHECK: used operator new
+// CHECK: MSConstexprAttr 0x{{[0-9a-f]+}} 
+[[nodiscard]] [[msvc::constexpr]] inline void* __cdecl operator new(decltype(sizeof(void*)), void* p) noexcept { return p; }
+
+// CHECK: used constexpr construct_at
+// CHECK: AttributedStmt 0x{{[0-9a-f]+}} 
+// CHECK-NEXT: MSConstexprAttr 0x{{[0-9a-f]+}} 
+// CHECK-NEXT: ReturnStmt 0x{{[0-9a-f]+}} 
+constexpr int* construct_at(int* p, int v) { [[msvc::constexpr]] return ::new (p) int(v); }
+
+constexpr bool check_construct_at() { int x; return *construct_at(&x, 42) == 42; }
+
+static_assert(check_construct_at());
Index: clang/test/AST/msvc-attrs.cpp
===
--- /dev/null
+++ clang/test/AST/msvc-attrs.cpp
@@ -0,0 +1,59 @@
+// RUN: %clang_cc1 -fms-extensions -std=c++20 -ast-dump %s | FileCheck %s
+
+// [[msvc::constexpr]] tests
+
+// MSConstexprDocs (1)
+// CHECK: used f1 'bool ()'
+// CHECK: MSConstexprAttr 0x{{[0-9a-f]+}} 
+[[msvc::constexpr]] bool f1() { return true; }
+
+// MSConstexprDocs (2)
+// CHECK: used constexpr f2 'bool ()'
+// CHECK: AttributedStmt 0x{{[0-9a-f]+}} 
+// CHECK-NEXT: MSConstexprAttr 0x{{[0-9a-f]+}} 
+// CHECK-NEXT: ReturnStmt 0x{{[0-9a-f]+}} 
+constexpr bool f2() { [[msvc::constexpr]] return f1(); }
+
+static_assert(f2());
+
+constexpr bool f3() { [[msvc::constexpr]] return f1() || f1() && f1(); }
+static_assert(f3());
+
+[[msvc::constexpr]] int f4(int x) { [[msvc::constexpr]] return x > 1 ? 1 + f4(x / 2) : 0; }
+constexpr bool f5() { [[msvc::constexpr]] return f4(32) == 5; }
+static_assert(f5());
+
+[[msvc::constexpr]] int f6(int x)
+{
+switch (x)
+{
+case 42: return 1337;
+default:
+ if (x < 0) [[msvc::constexpr]] return f4(-x);
+ else return x;
+}
+}
+
+constexpr bool f7() { [[msvc::constexpr]] return f6(f6(42) - 1337 + f6(-32) - 5 + (f6(1) ? f6(0) : f6(2))) == f6(0); }
+static_assert(f7());
+
+constexpr bool f8() { return true; }
+[[msvc::constexpr]] bool f9() { return f8(); }
+constexpr bool f10() { [[msvc::constexpr]] return f9(); }
+static_assert(f10());
+
+struct S1 {
+[[msvc::constexpr]] virtual bool vm() { return true; }
+constexpr bool cm() { [[msvc::constexpr]] return vm(); }
+};
+static_assert(S1{}.cm());
+
+/*
+// TODO: Add support for [[msvc::constexpr]] constructor
+struct S2 {
+[[msvc::constexpr]] S2() {}
+[[msvc::constexpr]] bool value() { return true; }
+static constexpr bool check() { [[msvc::constexpr]] return S2{}.value(); }
+};
+static_as

[PATCH] D133853: [AST] Add msvc-specific C++11 attributes

2022-09-14 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt created this revision.
Herald added a reviewer: aaron.ballman.
Herald added a subscriber: jdoerfert.
Herald added a project: All.
RIscRIpt requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

- 'msvc::no_tls_guard', first appeared in MSVC toolchain 14.25.28610
- 'msvc::known_semantics', first appeared in MSVC toolchain 14.27.29110
- 'msvc::noop_dtor', first appeared in MSVC toolchain 14.28.29333
- 'msvc::constexpr', first appeared in MSVC toolchain 14.33.31629

Closes #57696


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D133853

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/lib/AST/TypePrinter.cpp
  clang/lib/Sema/SemaStmtAttr.cpp
  clang/test/AST/msvc-attrs.cpp
  clang/test/Misc/pragma-attribute-supported-attributes-list.test

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
@@ -83,6 +83,9 @@
 // CHECK-NEXT: LoaderUninitialized (SubjectMatchRule_variable_is_global)
 // CHECK-NEXT: Lockable (SubjectMatchRule_record)
 // CHECK-NEXT: MIGServerRoutine (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_block)
+// CHECK-NEXT: MSConstexpr (SubjectMatchRule_function)
+// CHECK-NEXT: MSNoTlsGuard (SubjectMatchRule_variable)
+// CHECK-NEXT: MSNoopDtor (SubjectMatchRule_function)
 // CHECK-NEXT: MSStruct (SubjectMatchRule_record)
 // CHECK-NEXT: MaybeUndef (SubjectMatchRule_variable_is_parameter)
 // CHECK-NEXT: MicroMips (SubjectMatchRule_function)
Index: clang/test/AST/msvc-attrs.cpp
===
--- /dev/null
+++ clang/test/AST/msvc-attrs.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -fms-extensions -std=c++20 -DMSX -ast-dump %s | FileCheck %s
+// RUN: not %clang_cc1 -Werror=ignored-attributes -ast-dump %s 2>&1 | grep "8 errors generated"
+
+// CHECK: VarDecl 0x{{[0-9a-f]+}} <{{.*}}:[[@LINE+3]]:24, col:47> col:47 no_tls_guard_var
+// CHECK-NEXT: MSNoTlsGuardAttr 0x{{[0-9a-f]+}} 
+// CHECK-NEXT: ThreadAttr 0x{{[0-9a-f]+}} 
+[[msvc::no_tls_guard]] __declspec(thread) int no_tls_guard_var;
+
+// CHECK: MSKnownSemanticsAttr 0x{{[0-9a-f]+}} 
+// CHECK-NEXT: CXXRecordDecl 0x{{[0-9a-f]+}}  col:34
+struct [[msvc::known_semantics]] Struct {};
+
+// CHECK: TypeAliasDecl 0x{{[0-9a-f]+}}  col:7 Int 'int'
+// CHECK-NEXT: BuiltinType 0x{{[0-9a-f]+}} 'int'
+// CHECK-NEXT: MSKnownSemanticsAttr 0x{{[0-9a-f]+}} 
+using Int [[msvc::known_semantics]] = int;
+
+struct Dtor {
+  // CHECK: CXXDestructorDecl 0x{{[0-9a-f]+}}  col:23 ~Dtor 'void () noexcept'
+  // CHECK-NEXT: CompoundStmt 0x{{[0-9a-f]+}} 
+  // CHECK-NEXT: MSNoopDtorAttr 0x{{[0-9a-f]+}} 
+  [[msvc::noop_dtor]] ~Dtor() {}
+};
+
+// CHECK: FunctionDecl 0x{{[0-9a-f]+}}  col:27 New1 'void *(void *)'
+// CHECK: MSConstexprAttr 0x{{[0-9a-f]+}} 
+[[msvc::constexpr]] void *New1(void *where) { return where; }
+
+// CHECK: FunctionDecl {{.*}}  line:[[@LINE+4]]:17 constexpr New2
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: AttributedStmt
+// CHECK-NEXT: MSConstexprAttr
+constexpr char *New2() {
+  [[msvc::constexpr]] return ::new char[1];
+}
Index: clang/lib/Sema/SemaStmtAttr.cpp
===
--- clang/lib/Sema/SemaStmtAttr.cpp
+++ clang/lib/Sema/SemaStmtAttr.cpp
@@ -290,6 +290,12 @@
   return ::new (S.Context) UnlikelyAttr(S.Context, A);
 }
 
+static Attr *handleMSConstexpr(Sema &S, Stmt *St, const ParsedAttr &A,
+   SourceRange Range) {
+  // Validation is in Sema::ActOnAttributedStmt().
+  return ::new (S.Context) MSConstexprAttr(S.Context, A);
+}
+
 #define WANT_STMT_MERGE_LOGIC
 #include "clang/Sema/AttrParsedAttrImpl.inc"
 #undef WANT_STMT_MERGE_LOGIC
@@ -485,6 +491,8 @@
 return handleLikely(S, St, A, Range);
   case ParsedAttr::AT_Unlikely:
 return handleUnlikely(S, St, A, Range);
+  case ParsedAttr::AT_MSConstexpr:
+return handleMSConstexpr(S, St, A, Range);
   default:
 // N.B., ClangAttrEmitter.cpp emits a diagnostic helper that ensures a
 // declaration attribute is not written on a statement, but this code is
Index: clang/lib/AST/TypePrinter.cpp
===
--- clang/lib/AST/TypePrinter.cpp
+++ clang/lib/AST/TypePrinter.cpp
@@ -1745,6 +1745,7 @@
   case attr::AddressSpace:
   case attr::CmseNSCall:
   case attr::AnnotateType:
+  case attr::MSKnownSemantics:
 llvm_unreachable("This attribute should have been handled already");
 
   case attr::NSReturnsRetained:
Index: clang/include/clang/Basic/AttrDocs.td
===
--- clang/include/clang/Basic/AttrDocs.td
+++ clang/include/clang/Basic/AttrDocs.td
@@ -3478,6 +3478,41 @@
 }];
 }
 
+def M

[PATCH] D133853: [AST] Add msvc-specific C++11 attributes

2022-09-15 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added a comment.

In D133853#3792518 , @aaron.ballman 
wrote:

> I'm wondering what the goal is for these changes. ... Are you intending to 
> add semantics for these attributes in follow-up patches?

To be honest, I wasn't planning to do any of follow-up patches. I made a patch 
for internal usage at my job, and decided to submit it upstream.
The main reason I (we) need this patch is that we need to be able to parse 
MSVC-specific code (in the current case - detect `constexpr` functions). Since 
Visual Studio 17.3 (MSVC 14.33.31629), Microsoft's STL library added 
`[[msvc::constexpr]]` attribute, which is not documented yet, but makes a 
function to act like a `constexpr` function: see this godbolt sample 
 (i.e. forbids non-constexpr statements 
inside).

To make the patch complete, I decided to browse previous Microsoft's STL 
versions and see which vendor specific (`msvc::`) attributes they added 
previously; in this patch I added all attributes I was able to find.

> We don't typically add attributes to Clang that don't have any effect unless 
> there's a very compelling reason to do so.

Theoretically, I could re-submit (or adjust this) patch, which would add 
support for `[[msvc::constexpr]]` attribute with semantic meaning of 
`constexpr` for functions (for code parsed with `-fms-extensions` flag). 
Regarding other attributes - unfortunately they are either poorly documented, 
or not documented at all, so I can drop commits for these attributes.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133853

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


[PATCH] D133853: [AST] Add msvc-specific C++11 attributes

2022-09-17 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added a comment.

In D133853#3795579 , @aaron.ballman 
wrote:

> but my suggestion is to only support `[[msvc::constexpr]]` with the semantic 
> meaning of `constexpr`

Sounds good to me.

> It's a good question as to whether we want to support that only when passing 
> `-fms-extensions` or not (it seems like a generally useful attribute); we 
> don't do the same for GNU attributes, but maybe we don't want to follow that 
> pattern? This will be the first attribute we add with the `msvc` vendor 
> namespace.

IMO, this attribute is a clearly Microsoft's extension, thus it should be 
available only when `-fms-extensions` are enabled.

> If you find there's a good reason to upstream the other ones, we can 
> certainly consider it.

I don't see any good reason for other attributes to be added.

> FWIW, one Microsoft-specific attribute I know people have been asking about 
> is `[[msvc::no_unique_address]]`

Thanks for letting me know.

The current patch is my first attempt to contribute to LLVM; I am afraid it 
would take me some effort to implement semantics of 
`[[msvc::no_unique_address]]`, so I'd like to focus only on 
`[[msvc::constexpr]]` in current patch.

In D133853#3795598 , @erichkeane 
wrote:

> A functional `msvc::constexpr` would be acceptable, however, I'm having a 
> difficult time figuring out the purpose of it, it seems like it is just a 
> 'constexpr keyword' replacement?

I don't know how it works internally, but judging by its behavior - yes it's a 
`constexpr` replacement with some extended functionality (my guess is that they 
wanted to do some constexpr magic, and staying compatible with the standard at 
the same time), and there's a few information available online:

> Merged an MSVC-specific attribute, allowing the compiler to improve its 
> handling of constexpr dynamic allocation and constexpr unique_ptr. [1]



>   // Determine if we should use [[msvc::constexpr]] to allow for "extended 
> constexpr" in Visual C++. [2]

Browsing MSVC `14.33.31629` include headers I can see that this attribute is 
mostly used in `operator new` functions: either as a decorator of the function 
or the return statement.

I guess the best way to make this attribute compatible with MSVC would be ask 
someone at Microsoft, but I'm not sure who to reach out.

Meanwhile I'll adjust current patch to focus only `[[msvc::constexpr]]` 
attribute.

> I believe the 'unknown attribute' warning for them is superior to an ignored 
> attribute.

By the way, I'd like to take opportunity and ask what do you think of adding 
clang-specific compiler flag, which would add all unknown attributes to the AST 
in a string form (e.g. `[[attr1]] -> AST::UnknownAttr{"attr1"}`? Would you be 
interested in such patch?

[1] https://github.com/microsoft/STL/wiki/Changelog

[2] `14.33.31629\include\vcruntime.h`


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133853

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


[PATCH] D133853: [AST] Add msvc-specific C++11 attributes

2022-09-22 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added a comment.

In D133853#3799344 , @aaron.ballman 
wrote:

> It's a conforming extension in older language modes like C++98, where we 
> couldn't steal the `constexpr` keyword because it's not reserved, which is 
> one benefit to it. Does MSVC support this as far back as C++98?

Tbh, I cannot understand your question in relation to your statement, and where 
did you get that statement from 🙂

> Does MSVC support this as far back as C++98?

I don't know. AFAIK - no.

@h-vetinari thanks for your input.

I'll try to update this patch as per our discussion:

1. `[[msvc::constexpr]]` handle like `constexpr` for functions with 
`-fms-extensions` (according to MSVC error message: `C7687: [[msvc::constexpr]] 
may only be applied to statements and functions`); I won't implement semantic 
meaning for statements, as I am now aware of it and there's no constexpr effect 
on statements.
2. Possibly take a look at `[[msvc::no_unique_address]]`


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133853

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


[PATCH] D134458: [AST] Add msvc-specific C++11 attribute 'msvc::no_unique_address'

2022-09-22 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt created this revision.
Herald added a reviewer: aaron.ballman.
Herald added a project: All.
RIscRIpt requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D134458

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/Attr.td
  clang/lib/AST/Decl.cpp
  clang/lib/AST/RecordLayoutBuilder.cpp
  clang/lib/CodeGen/CGExprAgg.cpp
  clang/lib/CodeGen/CGExprConstant.cpp
  clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
  clang/lib/CodeGen/TargetInfo.cpp
  clang/test/AST/msvc-attrs.cpp

Index: clang/test/AST/msvc-attrs.cpp
===
--- clang/test/AST/msvc-attrs.cpp
+++ clang/test/AST/msvc-attrs.cpp
@@ -1,6 +1,14 @@
 // RUN: %clang_cc1 -fms-extensions -std=c++20 -ast-dump %s | FileCheck %s
-// RUN: not %clang_cc1 -Werror=ignored-attributes -ast-dump %s 2>&1 | grep "1 error generated"
+// RUN: not %clang_cc1 -Werror=ignored-attributes -ast-dump %s 2>&1 | grep "3 errors generated"
 
-// CHECK: msvc-attrs.cpp:[[@LINE+2]]:21, col:61> col:27 constexpr New1 'void *(void *)'
+struct Empty {};
+
+// CHECK:  col:27 constexpr New1 'void *(void *)'
 // CHECK: MSConstexprAttr 0x{{[0-9a-f]+}} 
 [[msvc::constexpr]] void *New1(void *where) { return where; }
+
+struct StructWithNUAField {
+  [[msvc::no_unique_address]] Empty e;
+  int f1;
+};
+static_assert(sizeof(StructWithNUAField) == sizeof(int)); // expected to fail without -fms-extensions
Index: clang/lib/CodeGen/TargetInfo.cpp
===
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -578,8 +578,7 @@
   // according to the Itanium ABI.  The exception applies only to records,
   // not arrays of records, so we must also check whether we stripped off an
   // array type above.
-  if (isa(RT->getDecl()) &&
-  (WasArray || !FD->hasAttr()))
+  if (isa(RT->getDecl()) && (WasArray || !FD->hasNoUniqueAddress()))
 return false;
 
   return isEmptyRecord(Context, FT, AllowArrays);
@@ -7524,8 +7523,7 @@
   // do count.  So do anonymous bitfields that aren't zero-sized.
 
   // Like isSingleElementStruct(), ignore C++20 empty data members.
-  if (FD->hasAttr() &&
-  isEmptyRecord(getContext(), FD->getType(), true))
+  if (FD->hasNoUniqueAddress() && isEmptyRecord(getContext(), FD->getType(), true))
 continue;
 
   // Unlike isSingleElementStruct(), arrays do not count.
Index: clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
===
--- clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -744,7 +744,7 @@
 Prior->Data = getByteArrayType(bitsToCharUnits(llvm::alignTo(
 cast(Prior->Data)->getIntegerBitWidth(), 8)));
   else {
-assert(Prior->FD->hasAttr() &&
+assert(Prior->FD->hasNoUniqueAddress() &&
"should not have reused this field's tail padding");
 Prior->Data = getByteArrayType(
 Context.getTypeInfoDataSizeInChars(Prior->FD->getType()).Width);
Index: clang/lib/CodeGen/CGExprConstant.cpp
===
--- clang/lib/CodeGen/CGExprConstant.cpp
+++ clang/lib/CodeGen/CGExprConstant.cpp
@@ -755,7 +755,7 @@
 return false;
   // After emitting a non-empty field with [[no_unique_address]], we may
   // need to overwrite its tail padding.
-  if (Field->hasAttr())
+  if (Field->hasNoUniqueAddress())
 AllowOverwrite = true;
 } else {
   // Otherwise we have a bitfield.
@@ -856,7 +856,7 @@
 return false;
   // After emitting a non-empty field with [[no_unique_address]], we may
   // need to overwrite its tail padding.
-  if (Field->hasAttr())
+  if (Field->hasNoUniqueAddress())
 AllowOverwrite = true;
 } else {
   // Otherwise we have a bitfield.
Index: clang/lib/CodeGen/CGExprAgg.cpp
===
--- clang/lib/CodeGen/CGExprAgg.cpp
+++ clang/lib/CodeGen/CGExprAgg.cpp
@@ -2015,7 +2015,7 @@
 
 AggValueSlot::Overlap_t
 CodeGenFunction::getOverlapForFieldInit(const FieldDecl *FD) {
-  if (!FD->hasAttr() || !FD->getType()->isRecordType())
+  if (!FD->hasNoUniqueAddress() || !FD->getType()->isRecordType())
 return AggValueSlot::DoesNotOverlap;
 
   // If the field lies entirely within the enclosing class's nvsize, its tail
Index: clang/lib/AST/RecordLayoutBuilder.cpp
===
--- clang/lib/AST/RecordLayoutBuilder.cpp
+++ clang/lib/AST/RecordLayoutBuilder.cpp
@@ -474,7 +474,7 @@
 
   // We are able to place the member variable at this offset.
   // Make sure to update the empty field subobject map.
-  UpdateEmptyFieldSubobjects(FD, Offset, FD->hasAttr());
+  UpdateEmpt

[PATCH] D133853: [AST] Add msvc-specific C++11 attributes

2022-09-22 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt added a comment.

I am new to `arc`, I tried `arc diff --edit --verbatim` as it's said in the 
docs, but it still created a new revision: https://reviews.llvm.org/D134458




Comment at: clang/lib/Sema/SemaStmtAttr.cpp:296
+  // Validation is in Sema::ActOnAttributedStmt().
+  return ::new (S.Context) MSConstexprAttr(S.Context, A);
+}

erichkeane wrote:
> Typically we try to do the ::Create function that is generated for 
> attributes, rather than placement new.  I realize we are consistently 
> inconsistent...
I could address this, but could you please provide an example? Because all 
`handle` functions in this file use placement new.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133853

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


[PATCH] D134458: [AST] Add msvc-specific C++11 attributes

2022-09-22 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 462234.
RIscRIpt retitled this revision from "[AST] Add msvc-specific C++11 attribute 
'msvc::no_unique_address'" to "[AST] Add msvc-specific C++11 attributes".
RIscRIpt edited the summary of this revision.
RIscRIpt added a comment.

Add msvc::constexpr commit


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134458

Files:
  clang/include/clang/AST/Decl.h
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/AST/Decl.cpp
  clang/lib/AST/RecordLayoutBuilder.cpp
  clang/lib/CodeGen/CGExprAgg.cpp
  clang/lib/CodeGen/CGExprConstant.cpp
  clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
  clang/lib/CodeGen/TargetInfo.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/AST/msvc-attrs.cpp

Index: clang/test/AST/msvc-attrs.cpp
===
--- /dev/null
+++ clang/test/AST/msvc-attrs.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -fms-extensions -std=c++20 -ast-dump %s | FileCheck %s
+// RUN: not %clang_cc1 -Werror=ignored-attributes -ast-dump %s 2>&1 | grep "3 errors generated"
+
+struct Empty {};
+
+// CHECK:  col:27 constexpr New1 'void *(void *)'
+// CHECK: MSConstexprAttr 0x{{[0-9a-f]+}} 
+[[msvc::constexpr]] void *New1(void *where) { return where; }
+
+struct StructWithNUAField {
+  [[msvc::no_unique_address]] Empty e;
+  int f1;
+};
+static_assert(sizeof(StructWithNUAField) == sizeof(int)); // expected to fail without -fms-extensions
Index: clang/lib/Sema/SemaDeclAttr.cpp
===
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -4992,6 +4992,9 @@
   case ParsedAttr::AT_PreserveAll:
 D->addAttr(::new (S.Context) PreserveAllAttr(S.Context, AL));
 return;
+  case ParsedAttr::AT_MSConstexpr:
+D->addAttr(::new (S.Context) MSConstexprAttr(S.Context, AL));
+return;
   default:
 llvm_unreachable("unexpected attribute kind");
   }
@@ -6975,6 +6978,14 @@
   D->addAttr(::new (S.Context) ThreadAttr(S.Context, AL));
 }
 
+static void handleMSConstexprAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+  if (auto *FD = dyn_cast(D))
+FD->setConstexprKind(ConstexprSpecKind::Constexpr);
+  else
+S.Diag(AL.getLoc(), diag::warn_attribute_ignored_on_non_function) << AL;
+  D->addAttr(::new (S.Context) MSConstexprAttr(S.Context, AL));
+}
+
 static void handleAbiTagAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   SmallVector Tags;
   for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
@@ -8912,6 +8923,9 @@
   case ParsedAttr::AT_Thread:
 handleDeclspecThreadAttr(S, D, AL);
 break;
+  case ParsedAttr::AT_MSConstexpr:
+handleMSConstexprAttr(S, D, AL);
+break;
 
   // HLSL attributes:
   case ParsedAttr::AT_HLSLNumThreads:
Index: clang/lib/CodeGen/TargetInfo.cpp
===
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -578,8 +578,7 @@
   // according to the Itanium ABI.  The exception applies only to records,
   // not arrays of records, so we must also check whether we stripped off an
   // array type above.
-  if (isa(RT->getDecl()) &&
-  (WasArray || !FD->hasAttr()))
+  if (isa(RT->getDecl()) && (WasArray || !FD->hasNoUniqueAddress()))
 return false;
 
   return isEmptyRecord(Context, FT, AllowArrays);
@@ -7524,8 +7523,7 @@
   // do count.  So do anonymous bitfields that aren't zero-sized.
 
   // Like isSingleElementStruct(), ignore C++20 empty data members.
-  if (FD->hasAttr() &&
-  isEmptyRecord(getContext(), FD->getType(), true))
+  if (FD->hasNoUniqueAddress() && isEmptyRecord(getContext(), FD->getType(), true))
 continue;
 
   // Unlike isSingleElementStruct(), arrays do not count.
Index: clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
===
--- clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -744,7 +744,7 @@
 Prior->Data = getByteArrayType(bitsToCharUnits(llvm::alignTo(
 cast(Prior->Data)->getIntegerBitWidth(), 8)));
   else {
-assert(Prior->FD->hasAttr() &&
+assert(Prior->FD->hasNoUniqueAddress() &&
"should not have reused this field's tail padding");
 Prior->Data = getByteArrayType(
 Context.getTypeInfoDataSizeInChars(Prior->FD->getType()).Width);
Index: clang/lib/CodeGen/CGExprConstant.cpp
===
--- clang/lib/CodeGen/CGExprConstant.cpp
+++ clang/lib/CodeGen/CGExprConstant.cpp
@@ -755,7 +755,7 @@
 return false;
   // After emitting a non-empty field with [[no_unique_address]], we may
   // need to overwrite its tail padding.
-  if (Field->hasAttr())
+ 

[PATCH] D134475: [clang-cl] Add support for [[msvc::constexpr]] C++11 attribute

2023-09-23 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt updated this revision to Diff 557270.
RIscRIpt added a comment.

Rebase onto main. Run lit clang/test. Bump.

Any chance we continue the review? I know it looked stale for a while I 
couldn't address review comments, but now I have time to work at this patch.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134475

Files:
  clang/docs/ReleaseNotes.rst
  clang/docs/UsersManual.rst
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/LangOptions.h
  clang/lib/AST/ExprConstant.cpp
  clang/lib/Basic/Targets/OSTargets.cpp
  clang/lib/Driver/ToolChains/MSVC.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaStmtAttr.cpp
  clang/test/AST/ms-constexpr.cpp
  clang/test/Driver/cl-options.c
  clang/test/Misc/pragma-attribute-supported-attributes-list.test
  clang/test/SemaCXX/ms-constexpr-invalid.cpp
  clang/test/SemaCXX/ms-constexpr-new.cpp
  clang/test/SemaCXX/ms-constexpr.cpp

Index: clang/test/SemaCXX/ms-constexpr.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/ms-constexpr.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++20 -verify %s
+// expected-no-diagnostics
+
+[[msvc::constexpr]] int log2(int x) { [[msvc::constexpr]] return x > 1 ? 1 + log2(x / 2) : 0; }
+constexpr bool test_log2() { [[msvc::constexpr]] return log2(32) == 5; }
+static_assert(test_log2());
+
+[[msvc::constexpr]] int get_value(int x)
+{
+  switch (x)
+  {
+case 42: return 1337;
+default:
+ if (x < 0) [[msvc::constexpr]] return log2(-x);
+ else return x;
+  }
+}
+
+constexpr bool test_complex_expr() {
+  [[msvc::constexpr]] return get_value(get_value(42) - 1337 + get_value(-32) - 5 + (get_value(1) ? get_value(0) : get_value(2))) == get_value(0);
+}
+static_assert(test_complex_expr());
+
+constexpr bool get_constexpr_true() { return true; }
+[[msvc::constexpr]] bool get_msconstexpr_true() { return get_constexpr_true(); }
+constexpr bool test_get_msconstexpr_true() { [[msvc::constexpr]] return get_msconstexpr_true(); }
+static_assert(test_get_msconstexpr_true());
+
+/*
+// TODO: Add support for [[msvc::constexpr]] constructor
+struct S2 {
+[[msvc::constexpr]] S2() {}
+[[msvc::constexpr]] bool value() { return true; }
+static constexpr bool check() { [[msvc::constexpr]] return S2{}.value(); }
+};
+static_assert(S2::check());
+*/
Index: clang/test/SemaCXX/ms-constexpr-new.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/ms-constexpr-new.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++20 -verify=supported %s
+// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.32 -std=c++20 -verify=unsupported %s
+// supported-no-diagnostics
+
+[[nodiscard]]
+[[msvc::constexpr]] // unsupported-warning {{unknown attribute 'constexpr' ignored}}
+inline void* __cdecl operator new(decltype(sizeof(void*)), void* p) noexcept { return p; }
+
+namespace std {
+  constexpr int* construct_at(int* p, int v) {
+[[msvc::constexpr]] return ::new (p) int(v); // unsupported-warning {{unknown attribute 'constexpr' ignored}}
+  }
+}
+
+constexpr bool check_construct_at() { int x; return *std::construct_at(&x, 42) == 42; }
+static_assert(check_construct_at());
Index: clang/test/SemaCXX/ms-constexpr-invalid.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/ms-constexpr-invalid.cpp
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++20 -verify %s
+// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++17 -verify %s
+
+// Check explicitly invalid code
+
+void runtime() {} // expected-note {{declared here}}
+
+[[msvc::constexpr]] void f0() { runtime(); } // expected-error {{[[msvc::constexpr]] function never produces a constant expression}} \
+ // expected-note {{non-constexpr function 'runtime' cannot be used in a constant expression}}
+[[msvc::constexpr]] constexpr void f1() {} // expected-error {{[[msvc::constexpr]] cannot be applied to a constexpr function 'f1'}}
+#if __cplusplus >= 202202L
+[[msvc::constexpr]] consteval void f2() {} // expected-error {{[[msvc::constexpr]] cannot be applied to a consteval function 'f2'}}
+#endif
+
+struct B1 {};
+struct D1 : virtual B1 { // expected-note {{virtual base class declared here}}
+[[msvc::constexpr]] D1() {} // expected-error {{constexpr constructor not allowed in struct with virtual base class}}
+};
+
+struct [[msvc::constexpr]] S2{}; // expected-error {{'constexpr' attribute only applies to functions and statements}}
+