[clang] [libc] [llvm] [NVPTX] Implement variadic functions using IR lowering (PR #96015)

2024-07-24 Thread Tom Honermann via cfe-commits

tahonermann wrote:

> Is it just the `char *` vs `void *`? We can probably change that back, in 
> fact I thought I did that in the patch but I might've forgotten to push the 
> update.

Yes. The local workaround we're currently using just unconditionally returns 
`CharPtrBuiltinVaList`.

https://github.com/llvm/llvm-project/pull/96015
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Fix null pointer dereference in enum debug info generation (PR #97105)

2024-07-24 Thread Tom Honermann via cfe-commits


@@ -98,3 +98,6 @@ enum E8 { A8 = -128, B8 = 127 } x8;
 // CHECK-NOT: DIFlagEnumClass
 // CHECK: !DIEnumerator(name: "A8", value: -128)
 
+// Forward declaration of an enum class.
+enum class Color : int;
+// CHECK-NOT: !DICompositeType(tag: DW_TAG_enumeration_type, name: "Color"

tahonermann wrote:

Please follow the naming patterns already used in the test and rename the new 
enumeration to `E9`.

I added this change to my local build, but the test still passes without the 
associated change to `clang/lib/CodeGen/CGDebugInfo.cpp`. That suggests this 
test doesn't actually exercise the code in question.

`EnumDecl::getDefinition()` (see 
[here](https://github.com/llvm/llvm-project/blob/8d3252a8987818171878a26e4298b4b5dbf2a7e9/clang/include/clang/AST/Decl.h#L3943-L3945))
  defers to `TagDecl::getDefinition()` (see 
[here](https://github.com/llvm/llvm-project/blob/8d3252a8987818171878a26e4298b4b5dbf2a7e9/clang/lib/AST/Decl.cpp#L4748-L4769)).
 The only way for the latter to return null is if `isCompleteDefinition()` (see 
[here](https://github.com/llvm/llvm-project/blob/8d3252a8987818171878a26e4298b4b5dbf2a7e9/clang/include/clang/AST/Decl.h#L3660))
 is false for every declaration of the enumeration. For 
`isCompleteDefinition()` to return true, there has to have been an earlier call 
to `setCompleteDefinition()`. There are few calls to that function, the only 
relevant one looks to be from `TagDecl::completeDefinition()` (see 
[here](https://github.com/llvm/llvm-project/blob/8d3252a8987818171878a26e4298b4b5dbf2a7e9/clang/lib/AST/Decl.cpp#L4736-L4746))
 by way of `EnumDecl::completeDefinition()` (see 
[here](https://github.com/llvm/llvm-project/blob/8d3252a8987818171878a26e4298b4b5dbf2a7e9/clang/lib/AST/Decl.cpp#L4866-L4877)).
 Auditing calls to `completeDefinition()` is a bit challenging, so I didn't 
check them all. The only obvious cases I see related to enumerations are calls 
related to when an enumeration definition is present. Based on that, I would 
expect the test to suffice to trigger a null dereference; unless 
`CGDebugInfo::CreateTypeDefinition()` is only called when a complete definition 
is available (in which case, the existing check for `isIncompleteType()` seems 
unnecessary and can be removed).

Can you do a bit more debugging to see if calls to 
`CGDebugInfo::CreateTypeDefinition(const EnumType *)` are in fact gated on a 
complete type definition? If they are, then the checks for `isIncompleteType()` 
can be removed and a non-null result from `ED->getDefinition()` can be asserted.

https://github.com/llvm/llvm-project/pull/97105
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Prevent null pointer dereference in designated initializer check (PR #97220)

2024-07-24 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann approved this pull request.

Thanks @smanna12, the change looks good!

https://github.com/llvm/llvm-project/pull/97220
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [libc] [llvm] [NVPTX] Implement variadic functions using IR lowering (PR #96015)

2024-07-24 Thread Tom Honermann via cfe-commits

tahonermann wrote:

The change to `NVPTXTargetInfo::getBuiltinVaListKind()` in 
`clang/lib/Basic/Targets/NVPTX.h` caused a regression in Intel's downstream 
Clang-based compiler when compiling SYCL code with device compilation targeting 
NVPTX. CUDA might be similarly impacted, but I haven't verified. There is no 
need to revert the change; we've backed out the relevant part of the change in 
our downstream fork for now. But we need to figure out a proper solution for 
the problem as described below.

SYCL compilation uses the host standard library headers for both host and 
device compilation. Microsoft's standard library headers define `va_list` as 
`char*` as shown at line 72 below:
```
...\Microsoft Visual 
Studio\2019\Professional\VC\Tools\MSVC\14.29.30133\include\vadefs.h:
 67 #ifndef _VA_LIST_DEFINED
 68#define _VA_LIST_DEFINED
 69#ifdef _M_CEE_PURE
 70typedef System::ArgIterator va_list;
 71#else
 72typedef char* va_list;
 73#endif
 74 #endif
 ..
 97 void  __cdecl __va_start(va_list*, ...);
 98 void* __cdecl __va_arg(va_list*, ...);
 99 void  __cdecl __va_end(va_list*);
100 
101 #define __crt_va_start_a(ap, v) ((void)(__va_start(, _ADDRESSOF(v), 
_SLOTSIZEOF(v), __alignof(v), _ADDRESSOF(v
102 #define __crt_va_arg(ap, t) (*(t *)__va_arg(, _SLOTSIZEOF(t), 
_APALIGN(t,ap), (t*)0))
103 #define __crt_va_end(ap)((void)(__va_end()))
```

The Clang driver interposes on Microsoft's `vadefs.h` header file by placing 
its own `vadefs.h` header file earlier in the header search path. This header 
overrides some of the macros defined by Microsoft's `vadefs.h` header file with 
ones that are intended to work with Clang's builtin variadic function support.
```
/clang/lib/Headers/vadefs.h:
 18 #include_next 
 19
 20 /* Override macros from vadefs.h with definitions that work with Clang. */
 ..
 34 /* VS 2015 switched to double underscore names, which is an improvement, 
but now
 35  * we have to intercept those names too.
 36  */
 37 #ifdef __crt_va_start
 38 #undef __crt_va_start
 39 #define __crt_va_start(ap, param) __builtin_va_start(ap, param)
 40 #endif
 41 #ifdef __crt_va_end
 42 #undef __crt_va_end
 43 #define __crt_va_end(ap)  __builtin_va_end(ap)
 44 #endif
 45 #ifdef __crt_va_arg
 46 #undef __crt_va_arg
 47 #define __crt_va_arg(ap, type)__builtin_va_arg(ap, type)
 48 #endif
```

The result is that invocations of the `__crt_va_start`, `__crt_va_end`, and 
`__crt_va_arg` macros in Microsoft standard library headers end up passing 
objects of the Microsoft defined `va_list` type (aka, `char*`) to builtin 
functions like `__builtin_va_start()` that expect objects of type 
`__builtin_va_list` (aka, `void*`) thus leading to compilation failures when 
compiling in C++ modes.

There are at least a few options available to try to address this.

1. Revert the change to `NVPTXTargetInfo::getBuiltinVaListKind()` so that 
`TargetInfo::CharPtrBuiltinVaList` is returned. I don't know what motivated 
that particular change, so I don't know how feasible this option is.
2. Modify `NVPTXTargetInfo::getBuiltinVaListKind()` to conditionally return a 
value based on which standard library is being used. I'm not sure how feasible 
this is either. There are currently two targets that conditionally return 
different values from their `getBuiltinVaListKind()` implementations; Hexagon 
(see 
[here](https://github.com/llvm/llvm-project/blob/8fd9624cf729dd722a170a9dfd8f725966515231/clang/lib/Basic/Targets/Hexagon.h#L106-L110)]
 and ARM (see 
[here](https://github.com/llvm/llvm-project/blob/8fd9624cf729dd722a170a9dfd8f725966515231/clang/lib/Basic/Targets/ARM.cpp#L1096-L1101)).
3. Modify Clang's `vadefs.h` header file to also interpose on Microsoft's 
definition of `va_list` with a change like the following. This could still lead 
to problems if `_VA_LIST_DEFINED` is already defined, if `va_list` is already 
declared (as `char*`), or in code that assumes that `va_list` is defined as 
`char*` in Microsoft environments.
```
 +  #ifndef _VA_LIST_DEFINED
 +  #define _VA_LIST_DEFINED
 +  typedef __builtin_va_list va_list;
 +  #endif
 18 #include_next 
```

Any thoughts on the above are much appreciated!

https://github.com/llvm/llvm-project/pull/96015
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Fix potential null pointer dereferences in Sema::AddInitializerToDecl (PR #94368)

2024-07-16 Thread Tom Honermann via cfe-commits


@@ -13681,12 +13681,13 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr 
*Init, bool DirectInit) {
 }
 
 Init = Result.getAs();
+assert(Init && "Init must not be null");
+
 IsParenListInit = !InitSeq.steps().empty() &&
   InitSeq.step_begin()->Kind ==
   InitializationSequence::SK_ParenthesizedListInit;
 QualType VDeclType = VDecl->getType();
-if (Init && !Init->getType().isNull() &&
-!Init->getType()->isDependentType() && !VDeclType->isDependentType() &&
+if (!Init->getType()->isDependentType() && !VDeclType->isDependentType() &&

tahonermann wrote:

I'm uncertain about this change. On the one hand, the assignment to `Init` 
looks to me like it must produce a non-null result due to the prior check to 
`Result.isInvalid()`. However, the following uses of `Init` were already 
guarded by a check for a non-null value, so the static analysis tool should not 
have complained about those.

Was the static analysis tool perhaps complaining about later uses of `Init`? 
Note that the assignment at line 13683 above is conditional (on 
`!VDecl->isInvalidDecl()`) and therefore might not suffice to ensure a definite 
non-null value. I haven't checked exhaustively if that is the case though.

https://github.com/llvm/llvm-project/pull/94368
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Fix potential null pointer dereferences in Sema::AddInitializerToDecl (PR #94368)

2024-07-16 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann commented:

Thanks @smanna12. I'm uncertain about this change; see my additional comment.

https://github.com/llvm/llvm-project/pull/94368
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Fix potential null pointer dereferences in Sema::AddInitializerToDecl (PR #94368)

2024-07-16 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann edited 
https://github.com/llvm/llvm-project/pull/94368
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Fix null pointer dereference in enum debug info generation (PR #97105)

2024-07-16 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann approved this pull request.

Thanks @smanna12. I think this looks ok; returning null here does appear to be 
consistent with other overloads of `CreateTypeDefinition` for `RecordType` and 
`ObjCInterfaceType`. I agree with @Michael137 that it would be nice to have an 
example that fails the added condition. The code already checks for an 
incomplete type so is presumably intended to handle such types. Perhaps we are 
missing a test though? Presumably one that uses a forward declareable enum type?

https://github.com/llvm/llvm-project/pull/97105
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Prevent null pointer dereference in TransformUnaryTransformType() (PR #97912)

2024-07-16 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann approved this pull request.

Looks good! Thanks @smanna12!

https://github.com/llvm/llvm-project/pull/97912
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Protect ObjCMethodList assignment operator against self-assignment (PR #97933)

2024-07-16 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann commented:

As far as I can tell, `ObjCMethodList` is already self-assignment safe so long 
as `PointerIntPair` is. It looks like the latter might not be though since its 
copy assignment operator (as implemented via `PunnedPointer`) uses `memcpy` and 
it does not guard against self-assignment. I wonder if a change should instead 
be made there. Can you share more details from the static analysis report?

https://github.com/llvm/llvm-project/pull/97933
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Diagnose use of deprecated template alias (PR #97619)

2024-07-16 Thread Tom Honermann via cfe-commits


@@ -0,0 +1,58 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+//
+// This test checks that a deprecated attribute on an alias
+// template triggers a warning diagnostic when it is used.
+
+template 
+struct NoAttr {
+  void foo() {}
+};
+
+// expected-note@+2 5{{'UsingWithAttr' has been explicitly marked deprecated 
here}}
+template 
+using UsingWithAttr __attribute__((deprecated)) = NoAttr;

tahonermann wrote:

I recommend adding a test that uses the C++11 `[[deprecated]]` attribute syntax.

https://github.com/llvm/llvm-project/pull/97619
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Fix Null Pointer Dereference in Sema::BuildClassMessageImplicit() (PR #90482)

2024-04-30 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann requested changes to this pull request.

I believe the static analyzer is reporting a false positive in this case. I 
don't think this change is correct. `BuildClassMessage()` only dereferences 
`receiverTypeInfo` if the provided source location is not valid. The existing 
`assert` already validates this case. The change would have the effect of 
eliding calls that are ok to make when `receiverTypeInfo` is null.

I think the right solution here is just to triage the static analysis report as 
a false positive.

https://github.com/llvm/llvm-project/pull/90482
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Prevent null pointer dereference in Sema::​CodeCompleteQualifiedId() (PR #90490)

2024-04-30 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann approved this pull request.

The change looks good to me. I recommend giving @sam-mccall a day or so to 
comment if he wants to.

https://github.com/llvm/llvm-project/pull/90490
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Prevent null pointer dereference in Sema::​CodeCompleteQualifiedId() (PR #90490)

2024-04-30 Thread Tom Honermann via cfe-commits

tahonermann wrote:

Adding Sam McCall as an additional reviewer since he originally authored this 
code in commit a76e68c9704fb5b3faf25bb8d51e405b5310ff08.

https://github.com/llvm/llvm-project/pull/90490
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] [NFC] Prevent null pointer dereference in Sema::InstantiateFunctionDefinition (PR #89801)

2024-04-23 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann approved this pull request.

Looks good to me, thanks @smanna12!

https://github.com/llvm/llvm-project/pull/89801
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [NFC][Clang] Fix potential dereferencing of nullptr (PR #86759)

2024-03-27 Thread Tom Honermann via cfe-commits


@@ -289,7 +289,7 @@ class ComplexExprEmitter
 const BinOpInfo );
 
   QualType GetHigherPrecisionFPType(QualType ElementType) {
-const auto *CurrentBT = dyn_cast(ElementType);
+const auto *CurrentBT = cast(ElementType);

tahonermann wrote:

This looks fine and is consistent with other type assumptions elsewhere in the 
same source file.

https://github.com/llvm/llvm-project/pull/86759
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [NFC][Clang] Fix potential dereferencing of nullptr (PR #86759)

2024-03-27 Thread Tom Honermann via cfe-commits


@@ -2974,7 +2974,7 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
 if (auto *FPrime = SemaRef.InstantiateFunctionDeclaration(
 F, TemplateArgListForBuildingFPrime, AliasTemplate->getLocation(),
 Sema::CodeSynthesisContext::BuildingDeductionGuides)) {
-  auto *GG = dyn_cast(FPrime);
+  auto *GG = cast(FPrime);

tahonermann wrote:

I think this looks fine too. It is not trivial to ensure, but seems reasonable.

https://github.com/llvm/llvm-project/pull/86759
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [NFC][Clang] Fix potential dereferencing of nullptr (PR #86759)

2024-03-27 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann edited 
https://github.com/llvm/llvm-project/pull/86759
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [NFC][Clang] Fix potential dereferencing of nullptr (PR #86759)

2024-03-27 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann approved this pull request.

Looks good, thanks @smanna12!

https://github.com/llvm/llvm-project/pull/86759
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [NFC][CLANG] Fix null pointer dereferences (PR #86760)

2024-03-27 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann approved this pull request.

Looks good, thanks @smanna12!

https://github.com/llvm/llvm-project/pull/86760
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [CLANG] Fix potential integer overflow value in getRVVTypeSize() (PR #86810)

2024-03-27 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann approved this pull request.

Thanks @smanna12. It looks like the revert happened in 
https://github.com/llvm/llvm-project/commit/c92ad411f2f94d8521cd18abcb37285f9a390ecb.
 Adding @topperc for awareness.

The change looks good to me and matches what was originally done in 
https://github.com/llvm/llvm-project/commit/7372c0d46d2185017c509eb30910b102b4f9cdaa.

https://github.com/llvm/llvm-project/pull/86810
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [NFC][CLANG] Fix static analyzer bugs about unnecessary object copies with auto keyword (PR #85962)

2024-03-26 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann approved this pull request.

This looks fine to me. `LambdaCapture` consists of a pointer and two source 
locations so is relatively small and thus, this doesn't address a performance 
concern. Having the variable be `const` is good regardless to avoid unintended 
mutation.

https://github.com/llvm/llvm-project/pull/85962
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [NFC][Clang] Fix potential dereferencing of nullptr (PR #85944)

2024-03-26 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann approved this pull request.

These all look good to me. Thanks, @smanna12!

https://github.com/llvm/llvm-project/pull/85944
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Correct Microsoft mangling of lifetime extended temporary objects. (PR #85529)

2024-03-25 Thread Tom Honermann via cfe-commits


@@ -54,6 +54,12 @@ ABI Changes in This Version
   inline member function that contains a static local variable with a dynamic
   initializer is declared with ``__declspec(dllimport)``. (#GH83616).
 
+- Fixed Microsoft name mangling of lifetime extended temporary objects. This
+  change corrects missing back reference registrations that could result in
+  incorrect back reference indexes and suprising demangled name results. Since
+  MSVC uses a different mangling for these objects, compatibility is not 
affected.
+  (#GH85423).

tahonermann wrote:

A new issue to address the inconsistent use of the `$S` mangling 
(as well as an additional issue with mangling of anonymous unions) has been 
filed as #86525.

https://github.com/llvm/llvm-project/pull/85529
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Correct Microsoft mangling of lifetime extended temporary objects. (PR #85529)

2024-03-25 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann closed 
https://github.com/llvm/llvm-project/pull/85529
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Correct Microsoft mangling of lifetime extended temporary objects. (PR #85529)

2024-03-16 Thread Tom Honermann via cfe-commits


@@ -54,6 +54,12 @@ ABI Changes in This Version
   inline member function that contains a static local variable with a dynamic
   initializer is declared with ``__declspec(dllimport)``. (#GH83616).
 
+- Fixed Microsoft name mangling of lifetime extended temporary objects. This
+  change corrects missing back reference registrations that could result in
+  incorrect back reference indexes and suprising demangled name results. Since
+  MSVC uses a different mangling for these objects, compatibility is not 
affected.
+  (#GH85423).

tahonermann wrote:

Commit 
https://github.com/llvm/llvm-project/commit/e77de75d7e009daaadb03e9b1091c3a9a9c9d311
 claims that Microsoft doesn't have a mangling for these objects and that the 
`$RT` mangling is a Clang invention. The claim that MSVC doesn't implement a 
mangling for these doesn't seem right though. Consider 
https://godbolt.org/z/n715zPbc6. It appears that MSVC (back to at least v19.14) 
uses a `$S` mangling for these; like that used for other unnamed 
objects like for structured bindings, anonymous unions, and (non-thread-safe) 
guards for static local variables. Further, I think 
https://godbolt.org/z/x1Kh57818 demonstrates a Clang/MSVC compatibility issue. 
The code Clang emits for `h()` for the inlining of `g()` attempts to import 
`__imp_?$RT1@singleton@?1??g@@YAHXZ@4ABUS@@B` while MSVC's code attempts to 
import `__imp_?$S1@?1??g@@YAHXZ@4US@@B`.

Assuming agreement with the analysis above, I'll file a new issue for the 
divergent mangling.

https://github.com/llvm/llvm-project/pull/85529
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Correct Microsoft mangling of lifetime extended temporary objects. (PR #85529)

2024-03-16 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann created 
https://github.com/llvm/llvm-project/pull/85529

Lifetime extended temporary objects that are bound to references with static 
storage duration may have external linkage and therefore require mangled symbol 
names.  Clang uses an extension of the Microsoft ABI to give these symbols an 
implicit name of '$RT' followed by a discriminator and then mangles them 
similarly to the variable they are bound to.  Clang's mangling scheme differs 
from the one used by MSVC.

Previously, the `$RT` portion of the name was not registered as 
a back reference candidate and this resulted in incorrect back references for 
enclosing class and/or namespace scopes that might be referenced in the type of 
the object.

This is an ABI change and has the potential to cause backward compatibility 
issues with previous Clang releases.  Since MSVC uses a different mangling 
scheme, this change does not affect compatibility with MSVC.

This fixes one of the name mangling concerns reported in #85423.

>From 4c0149e934aae9d061e22400eb3eace47e4906be Mon Sep 17 00:00:00 2001
From: Tom Honermann 
Date: Sat, 16 Mar 2024 07:09:58 -0700
Subject: [PATCH] [clang] Correct Microsoft mangling of lifetime extended
 temporary objects.

Lifetime extended temporary objects that are bound to references with static
storage duration may have external linkage and therefore require mangled symbol
names.  Clang uses an extension of the Microsoft ABI to give these symbols an
implicit name of '$RT' followed by a discriminator and then mangles them
similarly to the variable they are bound to.  Clang's mangling scheme differs
from the one used by MSVC.

Previously, the '$RT' portion of the name was not registered as
a back reference candidate and this resulted in incorrect back references for
enclosing class and/or namespace scopes that might be referenced in the
type of the object.

This is an ABI change and has the potential to cause backward compatibility
issues with previous Clang releases.  Since MSVC uses a different mangling
scheme, this change does not affect compatibility with MSVC.
---
 clang/docs/ReleaseNotes.rst |  6 ++
 clang/lib/AST/MicrosoftMangle.cpp   |  3 ++-
 clang/test/CodeGenCXX/mangle-ms-back-references.cpp | 13 +
 3 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 1ae35e6881d2f8..f0da6ca497b575 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -54,6 +54,12 @@ ABI Changes in This Version
   inline member function that contains a static local variable with a dynamic
   initializer is declared with ``__declspec(dllimport)``. (#GH83616).
 
+- Fixed Microsoft name mangling of lifetime extended temporary objects. This
+  change corrects missing back reference registrations that could result in
+  incorrect back reference indexes and suprising demangled name results. Since
+  MSVC uses a different mangling for these objects, compatibility is not 
affected.
+  (#GH85423).
+
 AST Dumping Potentially Breaking Changes
 
 
diff --git a/clang/lib/AST/MicrosoftMangle.cpp 
b/clang/lib/AST/MicrosoftMangle.cpp
index aa26bb7ed46f48..cf9c2093a8f6a1 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -3911,7 +3911,8 @@ void MicrosoftMangleContextImpl::mangleReferenceTemporary(
   msvc_hashing_ostream MHO(Out);
   MicrosoftCXXNameMangler Mangler(*this, MHO);
 
-  Mangler.getStream() << "?$RT" << ManglingNumber << '@';
+  Mangler.getStream() << "?";
+  Mangler.mangleSourceName("$RT" + llvm::utostr(ManglingNumber));
   Mangler.mangle(VD, "");
 }
 
diff --git a/clang/test/CodeGenCXX/mangle-ms-back-references.cpp 
b/clang/test/CodeGenCXX/mangle-ms-back-references.cpp
index b27a9c5acacb77..8707bff9534070 100644
--- a/clang/test/CodeGenCXX/mangle-ms-back-references.cpp
+++ b/clang/test/CodeGenCXX/mangle-ms-back-references.cpp
@@ -1,5 +1,18 @@
 // RUN: %clang_cc1 -fms-extensions -fblocks -emit-llvm %s -o - 
-triple=i386-pc-win32 | FileCheck %s
 
+namespace NS {
+// The name "RT1" for the name of the class below has been specifically
+// chosen to ensure that back reference lookup does not match against the
+// implicitly generated "$RT1" name of the reference temporary symbol.
+struct RT1 {
+  static const RT1& singleton;
+  int i;
+};
+const RT1& RT1::singleton = RT1{1};
+}
+// CHECK: "?$RT1@singleton@RT1@NS@@2ABU23@B"
+// CHECK: "?singleton@RT1@NS@@2ABU12@B"
+
 void f1(const char* a, const char* b) {}
 // CHECK: "?f1@@YAXPBD0@Z"
 

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


[clang] [clang][MSVC] Correct mangling of thread-safe static initialization variables. (PR #85300)

2024-03-15 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann closed 
https://github.com/llvm/llvm-project/pull/85300
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][MSVC] Correct mangling of thread-safe static initialization variables. (PR #85300)

2024-03-15 Thread Tom Honermann via cfe-commits


@@ -3920,7 +3920,8 @@ void 
MicrosoftMangleContextImpl::mangleThreadSafeStaticGuardVariable(
   msvc_hashing_ostream MHO(Out);
   MicrosoftCXXNameMangler Mangler(*this, MHO);
 
-  Mangler.getStream() << "?$TSS" << GuardNum << '@';
+  Mangler.getStream() << "?";
+  Mangler.mangleSourceName("$TSS" + llvm::utostr(GuardNum));

tahonermann wrote:

Done: https://github.com/llvm/llvm-project/issues/85423

https://github.com/llvm/llvm-project/pull/85300
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][MSVC] Correct mangling of thread-safe static initialization variables. (PR #85300)

2024-03-15 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann updated 
https://github.com/llvm/llvm-project/pull/85300

>From 0547c32ff324efa2bf7152326a342022527339a3 Mon Sep 17 00:00:00 2001
From: Tom Honermann 
Date: Thu, 14 Mar 2024 10:43:46 -0700
Subject: [PATCH] [clang][MSVC] Correct mangling of thread-safe static
 initialization variables.

Static local variables with dynamic initializers depend on implicitly defined
guard variables to synchronize thread-safe initialization.  These guard
variables may have external linkage and therefore require a stable name for
linkage purposes.  The Microsoft ABI assigns these variables a local name of
'$TSS' followed by a discriminator and mangles them as a static local variable
of type 'int'.  Previously, the '$TSS' portion of the name was
not registered as a back reference candidate and this resulted in incorrect
back references for enclosing class and/or namespace scopes that might be
referenced in the signature of the enclosing function.  This change adds the
previously missing back reference registration.  This matches the mangling
performed by MSVC and resolves incompatibilities when inline functions with
static local variables are inlined across DLL boundaries.

This is an ABI change and has the potential to cause backward compatibility
issues with previous Clang releases.

Fixes https://github.com/llvm/llvm-project/issues/83616
---
 clang/docs/ReleaseNotes.rst |  6 ++
 clang/lib/AST/MicrosoftMangle.cpp   |  5 +++--
 .../CodeGenCXX/mangle-ms-back-references.cpp| 17 +
 3 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index dfd88a128941ab..34acd88bbe0fb6 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -47,6 +47,12 @@ C++ Specific Potentially Breaking Changes
 
 ABI Changes in This Version
 ---
+- Fixed Microsoft name mangling of implicitly defined variables used for thread
+  safe static initialization of static local variables. This change resolves
+  incompatibilities with code compiled by MSVC but might introduce
+  incompatibilities with code compiled by earlier versions of Clang when an
+  inline member function that contains a static local variable with a dynamic
+  initializer is declared with ``__declspec(dllimport)``. (#GH83616).
 
 AST Dumping Potentially Breaking Changes
 
diff --git a/clang/lib/AST/MicrosoftMangle.cpp 
b/clang/lib/AST/MicrosoftMangle.cpp
index b272a546573a31..aa26bb7ed46f48 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -390,6 +390,7 @@ class MicrosoftCXXNameMangler {
   const FunctionDecl *D = nullptr,
   bool ForceThisQuals = false,
   bool MangleExceptionSpec = true);
+  void mangleSourceName(StringRef Name);
   void mangleNestedName(GlobalDecl GD);
 
 private:
@@ -408,7 +409,6 @@ class MicrosoftCXXNameMangler {
 mangleUnqualifiedName(GD, cast(GD.getDecl())->getDeclName());
   }
   void mangleUnqualifiedName(GlobalDecl GD, DeclarationName Name);
-  void mangleSourceName(StringRef Name);
   void mangleOperatorName(OverloadedOperatorKind OO, SourceLocation Loc);
   void mangleCXXDtorType(CXXDtorType T);
   void mangleQualifiers(Qualifiers Quals, bool IsMember);
@@ -3920,7 +3920,8 @@ void 
MicrosoftMangleContextImpl::mangleThreadSafeStaticGuardVariable(
   msvc_hashing_ostream MHO(Out);
   MicrosoftCXXNameMangler Mangler(*this, MHO);
 
-  Mangler.getStream() << "?$TSS" << GuardNum << '@';
+  Mangler.getStream() << "?";
+  Mangler.mangleSourceName("$TSS" + llvm::utostr(GuardNum));
   Mangler.mangleNestedName(VD);
   Mangler.getStream() << "@4HA";
 }
diff --git a/clang/test/CodeGenCXX/mangle-ms-back-references.cpp 
b/clang/test/CodeGenCXX/mangle-ms-back-references.cpp
index cb95c100b3d22e..b27a9c5acacb77 100644
--- a/clang/test/CodeGenCXX/mangle-ms-back-references.cpp
+++ b/clang/test/CodeGenCXX/mangle-ms-back-references.cpp
@@ -83,3 +83,20 @@ class H;
 
 void ManyParams(T01 &, T02 &, T03 &, T04 &, T05 &, T06 &, T07 &, T08 &, T09 &, 
T10 &, H &, H &) {}
 // CHECK: 
"?ManyParams@@YAXAAVT01@@AAVT02@@AAVT03@@AAVT04@@AAVT05@@AAVT06@@AAVT07@@AAVT08@@AAVT09@@AAVT10@@AAV?$H@VT11AAV?$H@VT11@Z"
+
+namespace NS {
+// The name "TSS0" for the name of the class below has been specifically
+// chosen to ensure that back reference lookup does not match against the
+// implicitly generated "$TSS0" name of the thread safe static initialization
+// variable.
+struct __declspec(dllexport) TSS0 {
+  static TSS0& get();
+  __forceinline static TSS0& singleton() {
+static TSS0& lsv = get();
+return lsv;
+  }
+};
+}
+// CHECK: "?singleton@TSS0@NS@@SAAAU12@XZ"
+// CHECK: "?lsv@?1??singleton@TSS0@NS@@SAAAU23@XZ@4AAU23@A"
+// CHECK: "?$TSS0@?1??singleton@TSS0@NS@@SAAAU23@XZ@4HA"

___

[clang] [clang] Fix Clang language extension documentation markup for __builtin_arm_trap. (PR #85310)

2024-03-15 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann closed 
https://github.com/llvm/llvm-project/pull/85310
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][nullability] allow _Nonnull etc on nullable class types (PR #82705)

2024-03-14 Thread Tom Honermann via cfe-commits


@@ -201,6 +201,21 @@ Attribute Changes in Clang
   and each must be a positive integer when provided. The parameter ``x`` is 
required, while ``y`` and
   ``z`` are optional with default value of 1.
 
+- The ``_Nullable`` and ``_Nonnull`` family of type attributes can now apply
+  to certain C++ class types, such as smart pointers:
+  ``void useObject(std::unique_ptr _Nonnull obj);``.
+
+  This works for standard library types including ``unique_ptr``, 
``shared_ptr``
+  and ``function``. See `the attribute reference
+documentation 
`_
+for the full list.

tahonermann wrote:

I'll just fix this with https://github.com/llvm/llvm-project/pull/85310.

https://github.com/llvm/llvm-project/pull/82705
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Fix Clang language extension documentation markup for __builtin_arm_trap. (PR #85310)

2024-03-14 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann updated 
https://github.com/llvm/llvm-project/pull/85310

>From 06f9e13e622f75a6a192c5bbe06e2facd3c0124d Mon Sep 17 00:00:00 2001
From: Tom Honermann 
Date: Thu, 14 Mar 2024 13:55:32 -0700
Subject: [PATCH 1/2] [clang] Fix Clang language extension documentation markup
 for __builtin_arm_trap.

---
 clang/docs/LanguageExtensions.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/docs/LanguageExtensions.rst 
b/clang/docs/LanguageExtensions.rst
index 9347703e96e21a..225736009d4869 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -3444,7 +3444,7 @@ Query for this feature with 
``__has_builtin(__builtin_debugtrap)``.
 Query for this feature with ``__has_builtin(__builtin_trap)``.
 
 ``__builtin_arm_trap``
---
+--
 
 ``__builtin_arm_trap`` is an AArch64 extension to ``__builtin_trap`` which 
also accepts a compile-time constant value, encoded directly into the trap 
instruction for later inspection.
 

>From e88e3fe1f5bea96a3c065e1e6d8305ca2e2ddde5 Mon Sep 17 00:00:00 2001
From: Tom Honermann 
Date: Thu, 14 Mar 2024 14:24:40 -0700
Subject: [PATCH 2/2] [clang] Fix Clang release note documentation markup for
 nullability attributes.

---
 clang/docs/ReleaseNotes.rst | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 459f6a25aeef7b..dfd88a128941ab 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -205,15 +205,15 @@ Attribute Changes in Clang
   to certain C++ class types, such as smart pointers:
   ``void useObject(std::unique_ptr _Nonnull obj);``.
 
-  This works for standard library types including ``unique_ptr``, 
``shared_ptr``
-  and ``function``. See `the attribute reference
-documentation 
`_
-for the full list.
+  This works for standard library types including ``unique_ptr``, 
``shared_ptr``,
+  and ``function``. See
+  `the attribute reference documentation 
`_
+  for the full list.
 
 - The ``_Nullable`` attribute can be applied to C++ class declarations:
   ``template  class _Nullable MySmartPointer {};``.
 
-  This allows the ``_Nullable`` and ``_Nonnull` family of type attributes to
+  This allows the ``_Nullable`` and ``_Nonnull`` family of type attributes to
   apply to this class.
 
 Improvements to Clang's diagnostics

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


[clang] [clang] Fix Clang language extension documentation markup for __builtin_arm_trap. (PR #85310)

2024-03-14 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann updated 
https://github.com/llvm/llvm-project/pull/85310

>From 06f9e13e622f75a6a192c5bbe06e2facd3c0124d Mon Sep 17 00:00:00 2001
From: Tom Honermann 
Date: Thu, 14 Mar 2024 13:55:32 -0700
Subject: [PATCH 1/2] [clang] Fix Clang language extension documentation markup
 for __builtin_arm_trap.

---
 clang/docs/LanguageExtensions.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/docs/LanguageExtensions.rst 
b/clang/docs/LanguageExtensions.rst
index 9347703e96e21a..225736009d4869 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -3444,7 +3444,7 @@ Query for this feature with 
``__has_builtin(__builtin_debugtrap)``.
 Query for this feature with ``__has_builtin(__builtin_trap)``.
 
 ``__builtin_arm_trap``
---
+--
 
 ``__builtin_arm_trap`` is an AArch64 extension to ``__builtin_trap`` which 
also accepts a compile-time constant value, encoded directly into the trap 
instruction for later inspection.
 

>From f1fe6f6e0a9a38569d13f93e7d2cd15730da178f Mon Sep 17 00:00:00 2001
From: Tom Honermann 
Date: Thu, 14 Mar 2024 14:24:40 -0700
Subject: [PATCH 2/2] [clang] Fix Clang release note documentation markup for
 nullability attributes.

---
 clang/docs/ReleaseNotes.rst | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 459f6a25aeef7b..52943b9f082934 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -205,10 +205,10 @@ Attribute Changes in Clang
   to certain C++ class types, such as smart pointers:
   ``void useObject(std::unique_ptr _Nonnull obj);``.
 
-  This works for standard library types including ``unique_ptr``, 
``shared_ptr``
-  and ``function``. See `the attribute reference
-documentation 
`_
-for the full list.
+  This works for standard library types including ``unique_ptr``, 
``shared_ptr``,
+  and ``function``. See
+  `the attribute reference documentation 
`_
+  for the full list.
 
 - The ``_Nullable`` attribute can be applied to C++ class declarations:
   ``template  class _Nullable MySmartPointer {};``.

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


[clang] [clang][nullability] allow _Nonnull etc on nullable class types (PR #82705)

2024-03-14 Thread Tom Honermann via cfe-commits


@@ -201,6 +201,21 @@ Attribute Changes in Clang
   and each must be a positive integer when provided. The parameter ``x`` is 
required, while ``y`` and
   ``z`` are optional with default value of 1.
 
+- The ``_Nullable`` and ``_Nonnull`` family of type attributes can now apply
+  to certain C++ class types, such as smart pointers:
+  ``void useObject(std::unique_ptr _Nonnull obj);``.
+
+  This works for standard library types including ``unique_ptr``, 
``shared_ptr``
+  and ``function``. See `the attribute reference
+documentation 
`_
+for the full list.

tahonermann wrote:

Doc builds seem to be unhappy with this change:
```
Warning, treated as error:
/home/runner/work/llvm-project/llvm-project/clang-build/tools/clang/docs/ReleaseNotes.rst:208:Inline
 interpreted text or phrase reference start-string without end-string.
```

The doc build run for this PR failed for a different reason that will be fixed 
by https://github.com/llvm/llvm-project/pull/85310.

https://github.com/llvm/llvm-project/pull/82705
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Fix Clang language extension documentation markup for __builtin_arm_trap. (PR #85310)

2024-03-14 Thread Tom Honermann via cfe-commits

tahonermann wrote:

@TNorthover, doc builds are failing because of this.
```
Warning, treated as error:
/home/runner/work/llvm-project/llvm-project/clang-build/tools/clang/docs/LanguageExtensions.rst:3447:Title
 underline too short.

``__builtin_arm_trap``
--
```

https://github.com/llvm/llvm-project/pull/85310
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Fix Clang language extension documentation markup for __builtin_arm_trap. (PR #85310)

2024-03-14 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann created 
https://github.com/llvm/llvm-project/pull/85310

None

>From 06f9e13e622f75a6a192c5bbe06e2facd3c0124d Mon Sep 17 00:00:00 2001
From: Tom Honermann 
Date: Thu, 14 Mar 2024 13:55:32 -0700
Subject: [PATCH] [clang] Fix Clang language extension documentation markup for
 __builtin_arm_trap.

---
 clang/docs/LanguageExtensions.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/docs/LanguageExtensions.rst 
b/clang/docs/LanguageExtensions.rst
index 9347703e96e21a..225736009d4869 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -3444,7 +3444,7 @@ Query for this feature with 
``__has_builtin(__builtin_debugtrap)``.
 Query for this feature with ``__has_builtin(__builtin_trap)``.
 
 ``__builtin_arm_trap``
---
+--
 
 ``__builtin_arm_trap`` is an AArch64 extension to ``__builtin_trap`` which 
also accepts a compile-time constant value, encoded directly into the trap 
instruction for later inspection.
 

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


[clang] [clang][MSVC] Correct mangling of thread-safe static initialization variables. (PR #85300)

2024-03-14 Thread Tom Honermann via cfe-commits


@@ -47,6 +47,12 @@ C++ Specific Potentially Breaking Changes
 
 ABI Changes in This Version
 ---
+- Fixed Microsoft name mangling of implicitly defined variables used for thread
+  safe static initialization of static local variables. This change resolves
+  incompatibilities with code compiled by MSVC but might introduce
+  incompatibilities with code compiled by earlier versions of Clang when an
+  inline member function that contains a static local variable with a dynamic
+  initializer is declared with ``__declspec(dllimport)``. (#GH83616).

tahonermann wrote:

Per discussion in https://github.com/llvm/llvm-project/issues/83616, I did not 
tie the fix to the `-fclang-abi-compat=` option. I checked for uses of 
`LangOptions::ClangABI` and while I see many such uses in `ItaniumMangle.cpp`, 
there are currently none in `MicrosoftMangle.cpp`.

https://github.com/llvm/llvm-project/pull/85300
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][MSVC] Correct mangling of thread-safe static initialization variables. (PR #85300)

2024-03-14 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann updated 
https://github.com/llvm/llvm-project/pull/85300

>From 76c7940df70bc9676a7880a849d16b2ede611258 Mon Sep 17 00:00:00 2001
From: Tom Honermann 
Date: Thu, 14 Mar 2024 10:43:46 -0700
Subject: [PATCH] [clang][MSVC] Correct mangling of thread-safe static
 initialization variables.

Static local variables with dynamic initializers depend on implicitly defined
guard variables to synchronize thread-safe initialization.  These guard
variables may have external linkage and therefore require a stable name for
linkage purposes.  The Microsoft ABI assigns these variables a local name of
'$TSS' followed by a discriminator and mangles them as a static local variable
of type 'int'.  Previously, the '$TSS' portion of the name was
not registered as a back reference candidate and this resulted in incorrect
back references for enclosing class and/or namespace scopes that might be
referenced in the signature of the enclosing function.  This change adds the
previously missing back reference registration.  This matches the mangling
performed by MSVC and resolves incompatibilities when inline functions with
static local variables are inlined across DLL boundaries.

This is an ABI change and has the potential to cause backward compatibility
issues with previous Clang releases.

Fixes https://github.com/llvm/llvm-project/issues/83616
---
 clang/docs/ReleaseNotes.rst |  6 ++
 clang/lib/AST/MicrosoftMangle.cpp   |  5 +++--
 .../CodeGenCXX/mangle-ms-back-references.cpp| 17 +
 3 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 8935a610722a31..1d7902671a18fd 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -47,6 +47,12 @@ C++ Specific Potentially Breaking Changes
 
 ABI Changes in This Version
 ---
+- Fixed Microsoft name mangling of implicitly defined variables used for thread
+  safe static initialization of static local variables. This change resolves
+  incompatibilities with code compiled by MSVC but might introduce
+  incompatibilities with code compiled by earlier versions of Clang when an
+  inline member function that contains a static local variable with a dynamic
+  initializer is declared with ``__declspec(dllimport)``. (#GH83616).
 
 AST Dumping Potentially Breaking Changes
 
diff --git a/clang/lib/AST/MicrosoftMangle.cpp 
b/clang/lib/AST/MicrosoftMangle.cpp
index b272a546573a31..aa26bb7ed46f48 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -390,6 +390,7 @@ class MicrosoftCXXNameMangler {
   const FunctionDecl *D = nullptr,
   bool ForceThisQuals = false,
   bool MangleExceptionSpec = true);
+  void mangleSourceName(StringRef Name);
   void mangleNestedName(GlobalDecl GD);
 
 private:
@@ -408,7 +409,6 @@ class MicrosoftCXXNameMangler {
 mangleUnqualifiedName(GD, cast(GD.getDecl())->getDeclName());
   }
   void mangleUnqualifiedName(GlobalDecl GD, DeclarationName Name);
-  void mangleSourceName(StringRef Name);
   void mangleOperatorName(OverloadedOperatorKind OO, SourceLocation Loc);
   void mangleCXXDtorType(CXXDtorType T);
   void mangleQualifiers(Qualifiers Quals, bool IsMember);
@@ -3920,7 +3920,8 @@ void 
MicrosoftMangleContextImpl::mangleThreadSafeStaticGuardVariable(
   msvc_hashing_ostream MHO(Out);
   MicrosoftCXXNameMangler Mangler(*this, MHO);
 
-  Mangler.getStream() << "?$TSS" << GuardNum << '@';
+  Mangler.getStream() << "?";
+  Mangler.mangleSourceName("$TSS" + llvm::utostr(GuardNum));
   Mangler.mangleNestedName(VD);
   Mangler.getStream() << "@4HA";
 }
diff --git a/clang/test/CodeGenCXX/mangle-ms-back-references.cpp 
b/clang/test/CodeGenCXX/mangle-ms-back-references.cpp
index cb95c100b3d22e..b27a9c5acacb77 100644
--- a/clang/test/CodeGenCXX/mangle-ms-back-references.cpp
+++ b/clang/test/CodeGenCXX/mangle-ms-back-references.cpp
@@ -83,3 +83,20 @@ class H;
 
 void ManyParams(T01 &, T02 &, T03 &, T04 &, T05 &, T06 &, T07 &, T08 &, T09 &, 
T10 &, H &, H &) {}
 // CHECK: 
"?ManyParams@@YAXAAVT01@@AAVT02@@AAVT03@@AAVT04@@AAVT05@@AAVT06@@AAVT07@@AAVT08@@AAVT09@@AAVT10@@AAV?$H@VT11AAV?$H@VT11@Z"
+
+namespace NS {
+// The name "TSS0" for the name of the class below has been specifically
+// chosen to ensure that back reference lookup does not match against the
+// implicitly generated "$TSS0" name of the thread safe static initialization
+// variable.
+struct __declspec(dllexport) TSS0 {
+  static TSS0& get();
+  __forceinline static TSS0& singleton() {
+static TSS0& lsv = get();
+return lsv;
+  }
+};
+}
+// CHECK: "?singleton@TSS0@NS@@SAAAU12@XZ"
+// CHECK: "?lsv@?1??singleton@TSS0@NS@@SAAAU23@XZ@4AAU23@A"
+// CHECK: "?$TSS0@?1??singleton@TSS0@NS@@SAAAU23@XZ@4HA"

___

[clang] [clang][MSVC] Correct mangling of thread-safe static initialization variables. (PR #85300)

2024-03-14 Thread Tom Honermann via cfe-commits


@@ -3920,7 +3920,8 @@ void 
MicrosoftMangleContextImpl::mangleThreadSafeStaticGuardVariable(
   msvc_hashing_ostream MHO(Out);
   MicrosoftCXXNameMangler Mangler(*this, MHO);
 
-  Mangler.getStream() << "?$TSS" << GuardNum << '@';
+  Mangler.getStream() << "?";
+  Mangler.mangleSourceName("$TSS" + llvm::utostr(GuardNum));

tahonermann wrote:

The inclusion of `$` in the source name is correct here. Without that, names 
might be incorrectly resolved to the implicit name of the guard variable. The 
added test checks for this. If `$` were not included in the source name, the 
mangled name for the guard variable would be:
- `?$TSS0@?1??singleton@ 0 NS@@SAAAU02@XZ@4HA`
instead of:
- `?$TSS0@?1??singleton@ TSS0@ NS@@SAAAU23@XZ@4HA`

Some brief searches for `mangleSourceName()` in `MicrosoftMangle.cpp` suggests 
there are quite a few cases of `@` *not* being included in the name registered 
as a back reference. These cases appear in the following functions. It is 
difficult to tell if these are intentional or are issues that should be fixed.
- `mangleObjCProtocol()`
- `mangleObjCLifetime()`
- `mangleObjCKindOfType()`
- `mangleAddressSpaceType()`
- `mangleType(const ComplexType *, ...)`
- `mangleType(const VectorType *, ...)`
- `mangleType(const ObjCObjectType *, ...)`
- `mangleType(const AtomicType *, ...)`
- `mangleType(const PipeType *, ...)`
- `mangleType(const BitIntType *, ...)`

There are also some other cases where it looks like a `$` prefixed name is 
included in the mangled name without being registered as a back reference. 
These are more difficult to spot without knowing the mangling scheme well. One 
such example is the one below. Should `$RT` be registered as a back reference? 
I didn't try to prove it one way or another.
- `mangleReferenceTemporary()`

https://github.com/llvm/llvm-project/pull/85300
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][MSVC] Correct mangling of thread-safe static initialization variables. (PR #85300)

2024-03-14 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann created 
https://github.com/llvm/llvm-project/pull/85300

Static local variables with dynamic initializers depend on implicitly defined 
guard variables to synchronize thread-safe initialization.  These guard 
variables may have external linkage and therefore require a stable name for 
linkage purposes.  The Microsoft ABI assigns these variables a local name of 
`$TSS` followed by a discriminator and mangles them as a static local variable 
of type `int`.  Previously, the `$TSS` portion of the name was 
not registered as a back reference candidate and this resulted in incorrect 
back references for enclosing class and/or namespace scopes that might be 
referenced in the signature of the enclosing function.  This change adds the 
previously missing back reference registration.  This matches the mangling 
performed by MSVC and resolves incompatibilities when inline functions with 
static local variables are inlined across DLL boundaries.

This is an ABI change and has the potential to cause backward compatibility 
issues with previous Clang releases.

>From 89bb7c94e6044ced4eb684cc19b0b5fcc5cc35fc Mon Sep 17 00:00:00 2001
From: Tom Honermann 
Date: Thu, 14 Mar 2024 10:43:46 -0700
Subject: [PATCH] [clang][MSVC] Correct mangling of thread-safe static
 initialization variables.

Static local variables with dynamic initializers depend on implicitly defined
guard variables to synchronize thread-safe initialization.  These guard
variables may have external linkage and therefore require a stable name for
linkage purposes.  The Microsoft ABI assigns these variables a local name of
'$TSS' followed by a discriminator and mangles them as a static local variable
of type 'int'.  Previously, the '$TSS' portion of the name was
not registered as a back reference candidate and this resulted in incorret
back references for enclosing class and/or namespace scopes that might be
referenced in the signature of the enclosing function.  This change adds the
previously missing back reference registration.  This matches the mangling
performed by MSVC and resolves incompatibilities when inline functions with
static local variables are inlined across DLL boundaries.

This is an ABI change and has the potential to cause backward compatibility
issues with previous Clang releases.
---
 clang/docs/ReleaseNotes.rst |  6 ++
 clang/lib/AST/MicrosoftMangle.cpp   |  5 +++--
 .../CodeGenCXX/mangle-ms-back-references.cpp| 17 +
 3 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 8935a610722a31..1d7902671a18fd 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -47,6 +47,12 @@ C++ Specific Potentially Breaking Changes
 
 ABI Changes in This Version
 ---
+- Fixed Microsoft name mangling of implicitly defined variables used for thread
+  safe static initialization of static local variables. This change resolves
+  incompatibilities with code compiled by MSVC but might introduce
+  incompatibilities with code compiled by earlier versions of Clang when an
+  inline member function that contains a static local variable with a dynamic
+  initializer is declared with ``__declspec(dllimport)``. (#GH83616).
 
 AST Dumping Potentially Breaking Changes
 
diff --git a/clang/lib/AST/MicrosoftMangle.cpp 
b/clang/lib/AST/MicrosoftMangle.cpp
index b272a546573a31..aa26bb7ed46f48 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -390,6 +390,7 @@ class MicrosoftCXXNameMangler {
   const FunctionDecl *D = nullptr,
   bool ForceThisQuals = false,
   bool MangleExceptionSpec = true);
+  void mangleSourceName(StringRef Name);
   void mangleNestedName(GlobalDecl GD);
 
 private:
@@ -408,7 +409,6 @@ class MicrosoftCXXNameMangler {
 mangleUnqualifiedName(GD, cast(GD.getDecl())->getDeclName());
   }
   void mangleUnqualifiedName(GlobalDecl GD, DeclarationName Name);
-  void mangleSourceName(StringRef Name);
   void mangleOperatorName(OverloadedOperatorKind OO, SourceLocation Loc);
   void mangleCXXDtorType(CXXDtorType T);
   void mangleQualifiers(Qualifiers Quals, bool IsMember);
@@ -3920,7 +3920,8 @@ void 
MicrosoftMangleContextImpl::mangleThreadSafeStaticGuardVariable(
   msvc_hashing_ostream MHO(Out);
   MicrosoftCXXNameMangler Mangler(*this, MHO);
 
-  Mangler.getStream() << "?$TSS" << GuardNum << '@';
+  Mangler.getStream() << "?";
+  Mangler.mangleSourceName("$TSS" + llvm::utostr(GuardNum));
   Mangler.mangleNestedName(VD);
   Mangler.getStream() << "@4HA";
 }
diff --git a/clang/test/CodeGenCXX/mangle-ms-back-references.cpp 
b/clang/test/CodeGenCXX/mangle-ms-back-references.cpp
index cb95c100b3d22e..b27a9c5acacb77 100644
--- a/clang/test/CodeGenCXX/mangle-ms-back-references.cpp
+++ 

[clang] [NFC][Clang] Fix Static Code Analysis Concerns with copy without assign (PR #75091)

2023-12-22 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann requested changes to this pull request.

I think the static analysis tool is confused here. The `SVEType` class doesn't 
actually have a user-declared copy constructor. It does have a constructor that 
delegates to the implicitly declared copy constructor though. The class members 
are all scalar types, so the implicitly declared copy constructor and 
assignment operator will both behave as expected.

I recommend triaging the static analysis report as a false positive and not 
making a source code change.

https://github.com/llvm/llvm-project/pull/75091
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [NFC][CLANG] Fix static analyzer bugs about unnecessary object copies with auto keyword (PR #75082)

2023-12-22 Thread Tom Honermann via cfe-commits


@@ -876,7 +876,7 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
   << PluginFN << toString(PassPlugin.takeError());
 }
   }
-  for (auto PassCallback : CodeGenOpts.PassBuilderCallbacks)
+  for (const auto  : CodeGenOpts.PassBuilderCallbacks)

tahonermann wrote:

`PassBuilderCallbacks` is defined as:
```
clang/include/clang/Basic/CodeGenOptions.h:
404   /// List of pass builder callbacks.
405   std::vector> 
PassBuilderCallbacks;
```
In the case where a `std::function` element wraps a lambda, copies can be 
expensive, so such avoidance makes sense. The `operator()` member of 
`std::function` is already `const` qualified, so the addition of `const` 
doesn't effect the behavior, at least not in the current language standards. 
Such calls are valid even when a mutable lambda is wrapped. That arguably 
results in a const violation, so there have been some papers that argued for 
changes ([N4348](https://wg21.link/n4348), [P0045](https://wg21.link/p0045)) 
but to my knowledge, the standard has not been changed.

This looks like a good change.

https://github.com/llvm/llvm-project/pull/75082
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [NFC][CLANG] Fix static analyzer bugs about unnecessary object copies with auto keyword (PR #75082)

2023-12-22 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann edited 
https://github.com/llvm/llvm-project/pull/75082
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [NFC][CLANG] Fix static analyzer bugs about unnecessary object copies with auto keyword (PR #75082)

2023-12-22 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann approved this pull request.

Looks good to me!

https://github.com/llvm/llvm-project/pull/75082
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Print more static_assert exprs (PR #74852)

2023-12-12 Thread Tom Honermann via cfe-commits

tahonermann wrote:

This looks like a good change to me since coercing a compiler to reveal the 
values of compile-time objects can be frustrating. We could really use 
something like `constexpr_print` from [P2758 (Emitting messages at compile 
time)](https://wg21.link/p2758).

https://github.com/llvm/llvm-project/pull/74852
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Mark WG14 N2939 (Identifier Syntax Fixes) as available in Clang 15 (PR #74666)

2023-12-07 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann closed 
https://github.com/llvm/llvm-project/pull/74666
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Mark WG14 N2939 (Identifier Syntax Fixes) as available in Clang 15 (PR #74666)

2023-12-07 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann updated 
https://github.com/llvm/llvm-project/pull/74666

>From fd5728ed346c097577d58c4c20dfc696f9b17740 Mon Sep 17 00:00:00 2001
From: Tom Honermann 
Date: Wed, 6 Dec 2023 14:27:25 -0800
Subject: [PATCH 1/2] [Clang] Mark WG14 N2939 (Identifier Syntax Fixes) as
 available in Clang 15

WG14 N2939 (Identifier Syntax Fixes) corrects a grammar issue in the C
standard but does not otherwise change intended behavior. This change
updates the C23 status to note this paper as implemented as of Clang 15;
the release in which support for N2836 (Identifier Syntax using Unicode
Standard Annex 31) was implemented.
---
 clang/test/C/C2x/n2836_n2939.c | 83 ++
 clang/www/c_status.html|  2 +-
 2 files changed, 84 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/C/C2x/n2836_n2939.c

diff --git a/clang/test/C/C2x/n2836_n2939.c b/clang/test/C/C2x/n2836_n2939.c
new file mode 100644
index 0..14095aa53456b
--- /dev/null
+++ b/clang/test/C/C2x/n2836_n2939.c
@@ -0,0 +1,83 @@
+// RUN: %clang_cc1 -x c -std=c2x -fsyntax-only -verify %s
+// RUN: %clang_cc1 -x c -std=c2x -E -DPP_ONLY=1 %s | FileCheck %s 
--strict-whitespace
+
+/* WG14 N2863: Clang 15
+ *   Identifier Syntax using Unicode Standard Annex 31
+ */
+
+/* WG14 N2939: Clang 15
+ *   Identifier Syntax Fixes
+ */
+
+// Some of the tests below are derived from clang/test/Lexer/unicode.c.
+
+// This file contains Unicode characters; please do not "fix" them!
+
+// No diagnostics for pragma directives.
+#pragma mark ¡Unicode!
+
+// lone non-identifier characters are allowed in preprocessing.
+#define COPYRIGHT Copyright © 2012
+#define XSTR(X) #X
+#define STR(X) XSTR(X)
+
+static const char *copyright = STR(COPYRIGHT); // no-warning
+// CHECK: static const char *copyright = "Copyright © {{2012}}";
+
+#if PP_ONLY
+COPYRIGHT
+// CHECK: Copyright © {{2012}}
+#endif
+
+// The characters in the following identifiers are no longer valid as either
+// start or continuation characters as of C23. These are taken from section 1
+// of N2836.
+extern int \N{CONSTRUCTION WORKER};  // expected-error {{expected identifier 
or '('}}
+extern int X\N{CONSTRUCTION WORKER}; // expected-error {{character  
not allowed in an identifier}}
+extern int \U0001F477;  // expected-error {{expected identifier or '('}}
+extern int X\U0001F477; // expected-error {{character  not allowed in 
an identifier}}
+extern int ;  // expected-error {{unexpected character }} \
+// expected-warning {{declaration does not declare anything}}
+extern int X; // expected-error {{character  not allowed in an 
identifier}}
+extern int ;  // expected-error {{unexpected character }} \
+// expected-warning {{declaration does not declare anything}}
+extern int X; // expected-error {{character  not allowed in an 
identifier}}
+extern int ;  // expected-error {{unexpected character }} \
+// expected-warning {{declaration does not declare anything}}
+extern int X; // expected-error {{character  not allowed in an 
identifier}}
+extern int ;  // expected-error {{unexpected character }} \
+// expected-warning {{declaration does not declare anything}}
+extern int X; // expected-error {{character  not allowed in an 
identifier}}
+extern int ;  // expected-error {{unexpected character }} \
+// expected-warning {{declaration does not declare anything}}
+extern int X; // expected-error {{character  not allowed in an 
identifier}}
+extern int ;  // expected-error {{unexpected character }} \
+// expected-warning {{declaration does not declare anything}}
+extern int X; // expected-error {{character  not allowed in an 
identifier}}
+
+// The characters in the following identifiers are not allowed as start
+// characters, but are allowed as continuation characters.
+extern int \N{ARABIC-INDIC DIGIT ZERO}; // expected-error {{expected 
identifier or '('}}
+extern int X\N{ARABIC-INDIC DIGIT ZERO};
+extern int \u0661; // expected-error {{expected identifier or '('}}
+extern int X\u0661;
+extern int ٢;  // expected-error {{character  not allowed at the start 
of an identifier}} \\
+   // expected-warning {{declaration does not declare anything}}
+extern int X٠;
+
+// The characters in the following identifiers are not valid start or
+// continuation characters in the standard, but are accepted as a conforming
+// extension.
+extern int \N{SUPERSCRIPT ZERO};  // expected-error {{expected identifier or 
'('}}
+extern int X\N{SUPERSCRIPT ZERO}; // expected-warning {{mathematical notation 
character  in an identifier is a Clang extension}}
+extern int \u00B9;  // expected-error {{expected identifier or '('}}
+extern int X\u00B9; // expected-warning {{mathematical notation character 
 in an identifier is a Clang extension}}
+extern int ²;  // expected-error {{character  not allowed at the start 
of an identifier}} \\
+   // 

[clang] [Clang] Mark WG14 N2939 (Identifier Syntax Fixes) as available in Clang 15 (PR #74666)

2023-12-07 Thread Tom Honermann via cfe-commits


@@ -0,0 +1,83 @@
+// RUN: %clang_cc1 -x c -std=c2x -fsyntax-only -verify %s
+// RUN: %clang_cc1 -x c -std=c2x -E -DPP_ONLY=1 %s | FileCheck %s 
--strict-whitespace
+
+/* WG14 N2863: Clang 15

tahonermann wrote:

Thank you, good catch!

https://github.com/llvm/llvm-project/pull/74666
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Mark WG14 N2939 (Identifier Syntax Fixes) as available in Clang 15 (PR #74666)

2023-12-06 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann created 
https://github.com/llvm/llvm-project/pull/74666

WG14 N2939 (Identifier Syntax Fixes) corrects a grammar issue in the C standard 
but does not otherwise change intended behavior. This change updates the C23 
status to note this paper as implemented as of Clang 15; the release in which 
support for N2836 (Identifier Syntax using Unicode Standard Annex 31) was 
implemented.

>From fd5728ed346c097577d58c4c20dfc696f9b17740 Mon Sep 17 00:00:00 2001
From: Tom Honermann 
Date: Wed, 6 Dec 2023 14:27:25 -0800
Subject: [PATCH] [Clang] Mark WG14 N2939 (Identifier Syntax Fixes) as
 available in Clang 15

WG14 N2939 (Identifier Syntax Fixes) corrects a grammar issue in the C
standard but does not otherwise change intended behavior. This change
updates the C23 status to note this paper as implemented as of Clang 15;
the release in which support for N2836 (Identifier Syntax using Unicode
Standard Annex 31) was implemented.
---
 clang/test/C/C2x/n2836_n2939.c | 83 ++
 clang/www/c_status.html|  2 +-
 2 files changed, 84 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/C/C2x/n2836_n2939.c

diff --git a/clang/test/C/C2x/n2836_n2939.c b/clang/test/C/C2x/n2836_n2939.c
new file mode 100644
index 00..14095aa53456b6
--- /dev/null
+++ b/clang/test/C/C2x/n2836_n2939.c
@@ -0,0 +1,83 @@
+// RUN: %clang_cc1 -x c -std=c2x -fsyntax-only -verify %s
+// RUN: %clang_cc1 -x c -std=c2x -E -DPP_ONLY=1 %s | FileCheck %s 
--strict-whitespace
+
+/* WG14 N2863: Clang 15
+ *   Identifier Syntax using Unicode Standard Annex 31
+ */
+
+/* WG14 N2939: Clang 15
+ *   Identifier Syntax Fixes
+ */
+
+// Some of the tests below are derived from clang/test/Lexer/unicode.c.
+
+// This file contains Unicode characters; please do not "fix" them!
+
+// No diagnostics for pragma directives.
+#pragma mark ¡Unicode!
+
+// lone non-identifier characters are allowed in preprocessing.
+#define COPYRIGHT Copyright © 2012
+#define XSTR(X) #X
+#define STR(X) XSTR(X)
+
+static const char *copyright = STR(COPYRIGHT); // no-warning
+// CHECK: static const char *copyright = "Copyright © {{2012}}";
+
+#if PP_ONLY
+COPYRIGHT
+// CHECK: Copyright © {{2012}}
+#endif
+
+// The characters in the following identifiers are no longer valid as either
+// start or continuation characters as of C23. These are taken from section 1
+// of N2836.
+extern int \N{CONSTRUCTION WORKER};  // expected-error {{expected identifier 
or '('}}
+extern int X\N{CONSTRUCTION WORKER}; // expected-error {{character  
not allowed in an identifier}}
+extern int \U0001F477;  // expected-error {{expected identifier or '('}}
+extern int X\U0001F477; // expected-error {{character  not allowed in 
an identifier}}
+extern int ;  // expected-error {{unexpected character }} \
+// expected-warning {{declaration does not declare anything}}
+extern int X; // expected-error {{character  not allowed in an 
identifier}}
+extern int ;  // expected-error {{unexpected character }} \
+// expected-warning {{declaration does not declare anything}}
+extern int X; // expected-error {{character  not allowed in an 
identifier}}
+extern int ;  // expected-error {{unexpected character }} \
+// expected-warning {{declaration does not declare anything}}
+extern int X; // expected-error {{character  not allowed in an 
identifier}}
+extern int ;  // expected-error {{unexpected character }} \
+// expected-warning {{declaration does not declare anything}}
+extern int X; // expected-error {{character  not allowed in an 
identifier}}
+extern int ;  // expected-error {{unexpected character }} \
+// expected-warning {{declaration does not declare anything}}
+extern int X; // expected-error {{character  not allowed in an 
identifier}}
+extern int ;  // expected-error {{unexpected character }} \
+// expected-warning {{declaration does not declare anything}}
+extern int X; // expected-error {{character  not allowed in an 
identifier}}
+
+// The characters in the following identifiers are not allowed as start
+// characters, but are allowed as continuation characters.
+extern int \N{ARABIC-INDIC DIGIT ZERO}; // expected-error {{expected 
identifier or '('}}
+extern int X\N{ARABIC-INDIC DIGIT ZERO};
+extern int \u0661; // expected-error {{expected identifier or '('}}
+extern int X\u0661;
+extern int ٢;  // expected-error {{character  not allowed at the start 
of an identifier}} \\
+   // expected-warning {{declaration does not declare anything}}
+extern int X٠;
+
+// The characters in the following identifiers are not valid start or
+// continuation characters in the standard, but are accepted as a conforming
+// extension.
+extern int \N{SUPERSCRIPT ZERO};  // expected-error {{expected identifier or 
'('}}
+extern int X\N{SUPERSCRIPT ZERO}; // expected-warning {{mathematical notation 
character  in an identifier is a Clang 

[lld] [llvm] [clang-tools-extra] [compiler-rt] [clang] [lldb] [flang] [libc] [libcxx] [Clang] Fix linker error for function multiversioning (PR #71706)

2023-12-05 Thread Tom Honermann via cfe-commits


@@ -4114,8 +4114,26 @@ void CodeGenModule::emitMultiVersionFunctions() {
 }
 
 llvm::Constant *ResolverConstant = GetOrCreateMultiVersionResolver(GD);
-if (auto *IFunc = dyn_cast(ResolverConstant))
+if (auto *IFunc = dyn_cast(ResolverConstant)) {
   ResolverConstant = IFunc->getResolver();
+  // In Aarch64, default versions of multiversioned functions are mangled 
to
+  // their 'normal' assembly name. This deviates from other targets which
+  // append a '.default' string. As a result we need to continue appending
+  // .ifunc in Aarch64.
+  // FIXME: Should Aarch64 mangling for 'default' multiversion function and
+  // in turn ifunc function match that of other targets?

tahonermann wrote:

Since `target_version` is new, I think it is reasonable to change its behavior 
(via a different github PR).

I suspect the `target` behavior is an artifact of how the multiversion function 
features evolved. My best guess is that the original implementation didn't 
support an indirect function facility that enabled dynamic resolution from 
outside a defining TU. Perhaps that was part of the motivation for adding 
`target_clones`.

I just discovered that gcc doesn't support the `target` attribute when 
compiling for C. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108964. I had 
been under the impression that it just didn't support overloading on the 
`target` attribute (but that the attribute still affected code generation). 
Interesting that no warning is given for an ignored attribute. Here is the 
example from the doc Elizabeth linked compiling as C. 
https://godbolt.org/z/asfrhG51G.

https://github.com/llvm/llvm-project/pull/71706
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[lld] [clang] [flang] [libcxx] [clang-tools-extra] [llvm] [compiler-rt] [lldb] [libc] [Clang] Fix linker error for function multiversioning (PR #71706)

2023-12-05 Thread Tom Honermann via cfe-commits


@@ -2515,6 +2515,12 @@ example, the following will emit 4 versions of the 
function:
 __attribute__((target_clones("arch=atom,avx2","arch=ivybridge","default")))
 void foo() {}
 
+Dispatch is done via ``ifunc`` mechanism. The assembler name of the indirect
+function is the original assembler name of the multiversioned function. For
+backward compatibility, an alias to this function is currently generated
+with an ``.ifunc`` suffix. This symbol is deprecated and may be removed
+in the future.
+

tahonermann wrote:

Not all x86/x86-64 targets support the ifunc feature.
```suggestion
For targets that support the GNU indirect function (IFUNC) feature, dispatch
is performed by emitting an indirect function that is resolved to the 
appropriate
target clone at load time. The indirect function is given the name the
multiversioned function would have if it had been declared without the 
attribute.
For backward compatibility with earlier Clang releases, a function alias with an
``.ifunc`` suffix is also emitted. The  ``.ifunc`` suffixed symbol is a 
deprecated
feature and support for it may be removed in the future.
```

https://github.com/llvm/llvm-project/pull/71706
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[lldb] [compiler-rt] [libcxx] [clang] [flang] [clang-tools-extra] [llvm] [lld] [libc] [Clang] Fix linker error for function multiversioning (PR #71706)

2023-12-05 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann edited 
https://github.com/llvm/llvm-project/pull/71706
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[flang] [libcxx] [lldb] [clang] [compiler-rt] [lld] [libc] [clang-tools-extra] [llvm] [Clang] Fix linker error for function multiversioning (PR #71706)

2023-12-05 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann approved this pull request.

This looks good to me. I suggested some edits to the doc; take or leave as you 
see fit!

https://github.com/llvm/llvm-project/pull/71706
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement P2308R1 - Template Parameter Initialization. (PR #73103)

2023-11-29 Thread Tom Honermann via cfe-commits


@@ -61,6 +61,14 @@ namespace dr2026 { // dr2026: 11
   }
 }
 
+namespace dr2049 { // dr2049: 18 drafting
+#if __cplusplus > 202002L
+template  struct X {};
+X<> a;
+X b;

tahonermann wrote:

Perhaps add a same-type static assertion for `a` and `b` to ensure a consistent 
specialization is selected?

https://github.com/llvm/llvm-project/pull/73103
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement P2308R1 - Template Parameter Initialization. (PR #73103)

2023-11-29 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann commented:

Looks like good work to me!

https://github.com/llvm/llvm-project/pull/73103
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement P2308R1 - Template Parameter Initialization. (PR #73103)

2023-11-29 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann edited 
https://github.com/llvm/llvm-project/pull/73103
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[llvm] [clang] [clang-tools-extra] [Clang] Fix linker error for function multiversioning (PR #71706)

2023-11-29 Thread Tom Honermann via cfe-commits

tahonermann wrote:

@elizabethandrews, PR #73688 seeks to enable ifunc support for Mach-o targets 
like Darwin. Collaboration might be required to avoid merge conflicts and/or 
build bot breakage depending on when changes land.

https://github.com/llvm/llvm-project/pull/71706
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-tools-extra] [llvm] [Clang] Fix linker error for function multiversioning (PR #71706)

2023-11-22 Thread Tom Honermann via cfe-commits


@@ -4282,10 +4300,19 @@ llvm::Constant 
*CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
   // Holds the name of the resolver, in ifunc mode this is the ifunc (which has
   // a separate resolver).
   std::string ResolverName = MangledName;
-  if (getTarget().supportsIFunc())
-ResolverName += ".ifunc";
-  else if (FD->isTargetMultiVersion())
+  if (getTarget().supportsIFunc()) {
+// In Aarch64, default versions of multiversioned functions are mangled to
+// their 'normal' assembly name. This deviates from other targets which
+// append a '.default' string. As a result we need to continue appending
+// .ifunc in Aarch64.
+// FIXME: Should Aarch64 mangling for 'default' multiversion function and
+// in turn ifunc function match that of other targets?

tahonermann wrote:

@DanielKristofKiss, please ensure this comment and FIXME is addressed/removed 
by your follow up patch.

https://github.com/llvm/llvm-project/pull/71706
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang] [llvm] [Clang] Fix linker error for function multiversioning (PR #71706)

2023-11-22 Thread Tom Honermann via cfe-commits


@@ -4114,8 +4114,26 @@ void CodeGenModule::emitMultiVersionFunctions() {
 }
 
 llvm::Constant *ResolverConstant = GetOrCreateMultiVersionResolver(GD);
-if (auto *IFunc = dyn_cast(ResolverConstant))
+if (auto *IFunc = dyn_cast(ResolverConstant)) {
   ResolverConstant = IFunc->getResolver();
+  // In Aarch64, default versions of multiversioned functions are mangled 
to
+  // their 'normal' assembly name. This deviates from other targets which
+  // append a '.default' string. As a result we need to continue appending
+  // .ifunc in Aarch64.
+  // FIXME: Should Aarch64 mangling for 'default' multiversion function and
+  // in turn ifunc function match that of other targets?
+  if (FD->isTargetClonesMultiVersion() &&
+  !getTarget().getTriple().isAArch64()) {
+const CGFunctionInfo  = getTypes().arrangeGlobalDeclaration(GD);
+llvm::FunctionType *DeclTy = getTypes().GetFunctionType(FI);
+std::string MangledName = getMangledNameImpl(
+*this, GD, FD, /*OmitMultiVersionMangling=*/true);
+auto *Alias = llvm::GlobalAlias::create(
+DeclTy, 0, getMultiversionLinkage(*this, GD),
+MangledName + ".ifunc", IFunc, ());
+SetCommonAttributes(FD, Alias);
+  }

tahonermann wrote:

This could use a comment that explains why a `.ifunc` alias is being emitted.

https://github.com/llvm/llvm-project/pull/71706
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [clang-tools-extra] [Clang] Fix linker error for function multiversioning (PR #71706)

2023-11-22 Thread Tom Honermann via cfe-commits


@@ -16,13 +16,22 @@
 // LINUX: @__cpu_model = external dso_local global { i32, i32, i32, [1 x i32] }
 // LINUX: @__cpu_features2 = external dso_local global [3 x i32]
 
-// LINUX: @internal.ifunc = internal ifunc i32 (), ptr @internal.resolver
-// LINUX: @foo.ifunc = weak_odr ifunc i32 (), ptr @foo.resolver
-// LINUX: @foo_dupes.ifunc = weak_odr ifunc void (), ptr @foo_dupes.resolver
-// LINUX: @unused.ifunc = weak_odr ifunc void (), ptr @unused.resolver
-// LINUX: @foo_inline.ifunc = weak_odr ifunc i32 (), ptr @foo_inline.resolver
-// LINUX: @foo_inline2.ifunc = weak_odr ifunc i32 (), ptr @foo_inline2.resolver
-// LINUX: @foo_used_no_defn.ifunc = weak_odr ifunc i32 (), ptr 
@foo_used_no_defn.resolver
+// LINUX: @internal.ifunc = internal alias i32 (), ptr @internal
+// LINUX: @foo.ifunc = weak_odr alias i32 (), ptr @foo
+// LINUX: @foo_dupes.ifunc = weak_odr alias void (), ptr @foo_dupes
+// LINUX: @unused.ifunc = weak_odr alias void (), ptr @unused
+// LINUX: @foo_inline.ifunc = weak_odr alias i32 (), ptr @foo_inline
+// LINUX: @foo_inline2.ifunc = weak_odr alias i32 (), ptr @foo_inline2
+// LINUX: @foo_used_no_defn.ifunc = weak_odr alias i32 (), ptr 
@foo_used_no_defn
+// LINUX: @isa_level.ifunc = weak_odr alias i32 (i32), ptr @isa_level
+
+// LINUX: @internal = internal ifunc i32 (), ptr @internal.resolver
+// LINUX: @foo = weak_odr ifunc i32 (), ptr @foo.resolver
+// LINUX: @foo_dupes = weak_odr ifunc void (), ptr @foo_dupes.resolver
+// LINUX: @unused = weak_odr ifunc void (), ptr @unused.resolver
+// LINUX: @foo_inline = weak_odr ifunc i32 (), ptr @foo_inline.resolver
+// LINUX: @foo_inline2 = weak_odr ifunc i32 (), ptr @foo_inline2.resolver
+// LINUX: @foo_used_no_defn = weak_odr ifunc i32 (), ptr 
@foo_used_no_defn.resolver

tahonermann wrote:

Since we're checking for `isa_level.ifunc` above, I think we should also check 
for `isa_level` here.

https://github.com/llvm/llvm-project/pull/71706
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang] [llvm] [Clang] Fix linker error for function multiversioning (PR #71706)

2023-11-22 Thread Tom Honermann via cfe-commits


@@ -4114,8 +4114,26 @@ void CodeGenModule::emitMultiVersionFunctions() {
 }
 
 llvm::Constant *ResolverConstant = GetOrCreateMultiVersionResolver(GD);
-if (auto *IFunc = dyn_cast(ResolverConstant))
+if (auto *IFunc = dyn_cast(ResolverConstant)) {
   ResolverConstant = IFunc->getResolver();
+  // In Aarch64, default versions of multiversioned functions are mangled 
to
+  // their 'normal' assembly name. This deviates from other targets which
+  // append a '.default' string. As a result we need to continue appending
+  // .ifunc in Aarch64.
+  // FIXME: Should Aarch64 mangling for 'default' multiversion function and
+  // in turn ifunc function match that of other targets?

tahonermann wrote:

@DanielKristofKiss, please ensure this comment and FIXME is addressed/removed 
by your follow up patch.

https://github.com/llvm/llvm-project/pull/71706
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang] [llvm] [Clang] Fix linker error for function multiversioning (PR #71706)

2023-11-22 Thread Tom Honermann via cfe-commits


@@ -555,6 +555,7 @@ Bug Fixes in This Version
   Fixes (`#67687 `_)
 - Fix crash from constexpr evaluator evaluating uninitialized arrays as rvalue.
   Fixes (`#67317 `_)
+- Fix linker error when using multiversioned function defined in a different 
TU.

tahonermann wrote:

```suggestion
- Fix the name of the ifunc symbol emitted for multiversion functions declared 
with the
  ``target_clones`` attribute. This addresses a linker error that would 
otherwise occur
  when these functions are referenced from other TUs.
```

https://github.com/llvm/llvm-project/pull/71706
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-tools-extra] [llvm] [Clang] Fix linker error for function multiversioning (PR #71706)

2023-11-22 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann requested changes to this pull request.

I requested some minor changes.

Can we document the `.ifunc` symbols as a deprecated feature? With this change, 
they will never be referenced except by code compiled by older compiler 
versions. Maybe plan to deprecate them a year from now?

It looks like there is a related issue in which multiple ifunc symbols are 
emitted for the `cpu_dispatch` attribute. See https://godbolt.org/z/71vr8ceza. 
The relevant symbols emitted are listed below. Note that both 
`_Z12cpu_specificv` and `_Z12cpu_specificv.ifunc` are "i" symbols with the same 
address. The caller in this case calls the `.ifunc` symbol (just as for 
`target_clones` prior to this change). It would be nice if we can fix this 
issue at the same time and likewise deprecate the `.ifunc` symbol for 
`cpu_dispatch`/`cpu_specific`.
```
24c0 i _Z12cpu_specificv
2480 T _Z12cpu_specificv.A
2490 T _Z12cpu_specificv.M
24c0 i _Z12cpu_specificv.ifunc
24c0 W _Z12cpu_specificv.resolver
```

I think the only time a symbol with a `.ifunc` suffix is actually needed is 
when the `target` attribute is used in an overloading context (since in that 
situation, the `target(default)` definition gets the non-suffixed name.

https://github.com/llvm/llvm-project/pull/71706
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [llvm] [clang] [Clang] Fix linker error for function multiversioning (PR #71706)

2023-11-22 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann edited 
https://github.com/llvm/llvm-project/pull/71706
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Diagnostics] Highlight code snippets (PR #66514)

2023-11-08 Thread Tom Honermann via cfe-commits
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= 
Message-ID:
In-Reply-To: 



@@ -0,0 +1,187 @@
+//===-- CodeSnippetHighlighter.cpp - Code snippet highlighting --*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "clang/Frontend/CodeSnippetHighlighter.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PreprocessorOptions.h"
+#include "llvm/Support/raw_ostream.h"
+#include 
+
+using namespace clang;
+
+static constexpr raw_ostream::Colors CommentColor = raw_ostream::GREEN;
+static constexpr raw_ostream::Colors LiteralColor = raw_ostream::CYAN;
+static constexpr raw_ostream::Colors KeywordColor = raw_ostream::BLUE;
+
+llvm::SmallVector CodeSnippetHighlighter::highlightLine(
+unsigned LineNumber, const Preprocessor *PP, const LangOptions ,
+FileID FID, const SourceManager , const char *LineStart) {
+  std::chrono::steady_clock::time_point begin =
+  std::chrono::steady_clock::now();
+
+  if (!PP)
+return {};
+
+  // Might cause emission of another diagnostic.
+  if (PP->getIdentifierTable().getExternalIdentifierLookup())
+return {};
+
+  size_t NTokens = 0;
+  // Classify the given token and append it to the given vector.
+  auto appendStyle = [PP, ](llvm::SmallVector ,
+ const Token , unsigned Start,
+ unsigned Length) -> void {
+if (T.is(tok::raw_identifier)) {
+  StringRef RawIdent = T.getRawIdentifier();
+  // Special case true/false/nullptr literals, since they will otherwise be
+  // treated as keywords.
+  if (RawIdent == "true" || RawIdent == "false" || RawIdent == "nullptr") {
+Vec.push_back(StyleRange{Start, Start + Length, LiteralColor});
+  } else {
+const IdentifierInfo *II = PP->getIdentifierInfo(RawIdent);
+assert(II);
+if (II->isKeyword(LangOpts))
+  Vec.push_back(StyleRange{Start, Start + Length, KeywordColor});
+  }
+} else if (tok::isLiteral(T.getKind())) {
+  Vec.push_back(StyleRange{Start, Start + Length, LiteralColor});
+} else {
+  assert(T.is(tok::comment));
+  Vec.push_back(StyleRange{Start, Start + Length, CommentColor});
+}
+  };
+
+  // Figure out where to start lexing from.
+  auto Buff = SM.getBufferOrNone(FID);
+  assert(Buff);
+  Lexer L = Lexer(FID, *Buff, SM, LangOpts);
+  L.SetKeepWhitespaceMode(true);
+
+  // Seek to the last save point before the start of the line.
+  if (const char *Save = PP->getSaveFor(LineStart);
+  Buff->getBufferStart() <= Save && Save < Buff->getBufferEnd()) {
+size_t Offset = Save - Buff->getBufferStart();
+assert(Save >= Buff->getBufferStart());
+assert(Save <= Buff->getBufferEnd());
+
+L.seek(Offset, /*IsAtStartOfLine=*/true);
+  }
+
+  llvm::SmallVector LineRanges;
+  bool Stop = false;
+  while (!Stop) {
+++NTokens;
+Token T;
+Stop = L.LexFromRawLexer(T);
+if (T.is(tok::unknown))
+  continue;
+
+// We are only interested in identifiers, literals and comments.
+if (!T.is(tok::raw_identifier) && !T.is(tok::comment) &&
+!tok::isLiteral(T.getKind()))
+  continue;
+
+bool Invalid = false;
+unsigned EndLine = SM.getSpellingLineNumber(T.getEndLoc(), ) - 1;
+if (Invalid)
+  continue;
+
+if (EndLine < LineNumber)
+  continue;
+unsigned StartLine =
+SM.getSpellingLineNumber(T.getLocation(), ) - 1;
+if (Invalid)
+  continue;
+if (StartLine > LineNumber)
+  break;
+
+// Must have an intersection at this point
+assert(StartLine <= LineNumber && EndLine >= LineNumber);
+
+unsigned StartCol =
+SM.getSpellingColumnNumber(T.getLocation(), ) - 1;
+if (Invalid)
+  continue;
+
+// Simple tokens.
+if (StartLine == EndLine) {
+  appendStyle(LineRanges, T, StartCol, T.getLength());
+  continue;
+}
+unsigned NumLines = EndLine - StartLine;
+assert(NumLines >= 1);
+
+// For tokens that span multiple lines (think multiline comments), we
+// divide them into multiple StyleRanges.
+unsigned EndCol = SM.getSpellingColumnNumber(T.getEndLoc(), ) - 1;
+if (Invalid)
+  

[clang] [Clang] Fix a crash when using ast-dump=json (PR #70224)

2023-11-08 Thread Tom Honermann via cfe-commits


@@ -697,6 +697,8 @@ Miscellaneous Clang Crashes Fixed
   `Issue 64564 `_
 - Fixed a crash when an ObjC ivar has an invalid type. See
   (`#68001 `_)
+- Fixed a crash when ``-ast-dump=json`` was used for code using template
+  deduction guides.

tahonermann wrote:

```suggestion
- Fixed a crash when ``-ast-dump=json`` was used for code using class
  template deduction guides.
```

https://github.com/llvm/llvm-project/pull/70224
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Fix a crash when using ast-dump=json (PR #70224)

2023-11-08 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann approved this pull request.

I added a minor suggested change for the release note, but this otherwise looks 
good to me.

https://github.com/llvm/llvm-project/pull/70224
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Fix a crash when using ast-dump=json (PR #70224)

2023-11-08 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann edited 
https://github.com/llvm/llvm-project/pull/70224
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [CUDA][HIP] Fix deduction guide (PR #69366)

2023-11-01 Thread Tom Honermann via cfe-commits

tahonermann wrote:

For what it is worth, the described behavior sounds right to me from a design 
perspective. The fact that it matches `nvcc` behavior is a very good hint that 
it is the desired behavior as well. I haven't reviewed the code changes, but as 
long as they implement what is described, I'd give this a thumbs up.

https://github.com/llvm/llvm-project/pull/69366
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Fix a crash when using ast-dump=json (PR #70224)

2023-10-27 Thread Tom Honermann via cfe-commits


@@ -217,21 +221,21 @@ void i();
 // CHECK-NEXT:"id": "0x{{.*}}",
 // CHECK-NEXT:"kind": "FunctionTemplateDecl",
 // CHECK-NEXT:"loc": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 142,

tahonermann wrote:

Reverting the undesired changes suffices for me. My Python experience is years 
out of date too :)

https://github.com/llvm/llvm-project/pull/70224
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Warn on deprecated specializations used in system headers. (PR #70353)

2023-10-26 Thread Tom Honermann via cfe-commits

tahonermann wrote:

I like this very much so long as it doesn't turn out to be too noisy!

https://github.com/llvm/llvm-project/pull/70353
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Fix a crash when using ast-dump=json (PR #70224)

2023-10-26 Thread Tom Honermann via cfe-commits


@@ -217,21 +221,21 @@ void i();
 // CHECK-NEXT:"id": "0x{{.*}}",
 // CHECK-NEXT:"kind": "FunctionTemplateDecl",
 // CHECK-NEXT:"loc": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 142,

tahonermann wrote:

Hmm, the regex changes were made in 
https://github.com/llvm/llvm-project/commit/6d8e5c968538eff2c024d46d5715de0828a69407
 by Chris Bieneman and reviewed by Aaron in https://reviews.llvm.org/D119362. 
It looks like those regex changes need to be preserved. It seems that script 
could use an update. Perhaps follow up with Chris?

https://github.com/llvm/llvm-project/pull/70224
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Fix a crash when using ast-dump=json (PR #70224)

2023-10-25 Thread Tom Honermann via cfe-commits


@@ -217,21 +221,21 @@ void i();
 // CHECK-NEXT:"id": "0x{{.*}}",
 // CHECK-NEXT:"kind": "FunctionTemplateDecl",
 // CHECK-NEXT:"loc": {
-// CHECK-NEXT: "offset": {{[0-9]+}},
+// CHECK-NEXT: "offset": 142,

tahonermann wrote:

It looks like a regular expression was previously used to avoid sensitivity to 
the `offset` values. I'm not familiar with this test, but I see the comment 
above regarding using `gen_ast_dump_json_test.py` to generate the `CHECK` 
lines. Did you use that script?

https://github.com/llvm/llvm-project/pull/70224
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Driver] Ignore non-clang pch files when -include a.h probes a.h.gch (PR #69204)

2023-10-17 Thread Tom Honermann via cfe-commits

https://github.com/tahonermann approved this pull request.

This looks great to me. Thank you for working on this!

Please give @MaskRay a chance to comment on this before merging it.

https://github.com/llvm/llvm-project/pull/69204
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][modules] Remove preloaded SLocEntries from PCM files (PR #66962)

2023-10-03 Thread Tom Honermann via cfe-commits

tahonermann wrote:

> That said, isBeforeInTranslationUnit is slow already, and I don't think it's 
> hot in clang, moreso in tools like clang-tidy whose performance is 
> less-critical. So let's make it right, and then optimize it again if problems 
> arise.

It may not be a hot function in Clang itself, but it is quite hot for some 
downstream Clang forks. While at Coverity, I had to avoid direct use of it 
because it was far too slow. Anything that speeds it up would be appreciated.

https://github.com/llvm/llvm-project/pull/66962
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Driver] -include: deprecate probing .gch (PR #67084)

2023-09-28 Thread Tom Honermann via cfe-commits

tahonermann wrote:

I am also rather uncomfortable with this behavioral change. There are a lot of 
build systems in use out there. My preference would be to continue to probe for 
a .gch file, but also validate that it is a (compatible) Clang PCH file before 
trying to use it.

https://github.com/llvm/llvm-project/pull/67084
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 256a0b2 - [clang] Correct source locations for instantiations of function templates.

2023-09-18 Thread Tom Honermann via cfe-commits

Author: Tom Honermann
Date: 2023-09-18T12:51:45-07:00
New Revision: 256a0b298c68b89688b80350b034daf2f7785b67

URL: 
https://github.com/llvm/llvm-project/commit/256a0b298c68b89688b80350b034daf2f7785b67
DIFF: 
https://github.com/llvm/llvm-project/commit/256a0b298c68b89688b80350b034daf2f7785b67.diff

LOG: [clang] Correct source locations for instantiations of function templates.

This change corrects some cases where the source location for an
instantiated specialization of a function template or a member function
of a class template was assigned the location of a non-defining
declaration rather than the location of the definition the
specialization was instantiated from.

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

Reviewed By: cor3ntin

Differential Revision: https://reviews.llvm.org/D64087

Added: 


Modified: 
clang/docs/ReleaseNotes.rst
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
clang/test/CXX/class/class.compare/class.compare.default/p1.cpp
clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
clang/test/SemaCXX/member-init.cpp
clang/test/SemaTemplate/virtual-member-functions.cpp

Removed: 




diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 500f9c9a0cda741..7e964f6eb435bb0 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -291,6 +291,12 @@ Bug Fixes to C++ Support
   pointers on win32.
   (`#62594 `_)
 
+- Fixed some cases where the source location for an instantiated specialization
+  of a function template or a member function of a class template was assigned
+  the location of a non-defining declaration rather than the location of the
+  definition the specialization was instantiated from.
+  (`#26057 `_`)
+
 Bug Fixes to AST Handling
 ^
 - Fixed an import failure of recursive friend class template.

diff  --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp 
b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 37a7d6204413a38..fa839e9b71a3cf9 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -4990,8 +4990,10 @@ void Sema::InstantiateFunctionDefinition(SourceLocation 
PointOfInstantiation,
   // unimported module.
   Function->setVisibleDespiteOwningModule();
 
-  // Copy the inner loc start from the pattern.
+  // Copy the source locations from the pattern.
+  Function->setLocation(PatternDecl->getLocation());
   Function->setInnerLocStart(PatternDecl->getInnerLocStart());
+  Function->setRangeEnd(PatternDecl->getEndLoc());
 
   EnterExpressionEvaluationContext EvalContext(
   *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);

diff  --git a/clang/test/CXX/class/class.compare/class.compare.default/p1.cpp 
b/clang/test/CXX/class/class.compare/class.compare.default/p1.cpp
index b595825e1750adc..252860bfc4de077 100644
--- a/clang/test/CXX/class/class.compare/class.compare.default/p1.cpp
+++ b/clang/test/CXX/class/class.compare/class.compare.default/p1.cpp
@@ -209,10 +209,10 @@ bool operator==(e *, int *) = default; // 
expected-error{{must have at least one
 
 namespace p2085_2 {
 template  struct S6 {
-  // expected-error@+2{{found 'const int &'}}
-  // expected-error@+1{{found 'const float &'}}
   bool operator==(T const &) const;
 };
+// expected-error@+2{{found 'const int &'}}
+// expected-error@+1{{found 'const float &'}}
 template  bool S6::operator==(T const &) const = default;
 
 template struct S6; // expected-note{{S6::operator==' requested}}

diff  --git a/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp 
b/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
index c5eb7f139327505..def3bbb8adf0fce 100644
--- a/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
+++ b/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
@@ -102,14 +102,14 @@ constexpr int f(T t) {
 
 namespace forward_declare_consteval{
 template 
-constexpr int f(T t);  // expected-note {{'f' defined here}}
+constexpr int f(T t);
 
 auto a = ;
 auto b = ; // expected-error {{immediate function 'f' used before 
it is defined}} \
   // expected-note {{in instantiation of function template 
specialization}}
 
 template 
-constexpr int f(T t) {
+constexpr int f(T t) { // expected-note {{'f' defined here}}
 return id(t); // expected-note {{'f' is an immediate function because 
its body contains a call to a consteval function 'id' and that call is not a 
constant expression}}
 }
 }

diff  --git a/clang/test/SemaCXX/member-init.cpp 
b/clang/test/SemaCXX/member-init.cpp
index e98a66ca9cab9f4..087561e679f4eae 100644
--- a/clang/test/SemaCXX/member-init.cpp
+++ b/clang/test/SemaCXX/member-init.cpp
@@ -164,11 +164,11 @@ struct A {
 
 namespace explicit_instantiation {
 template struct X {
-  X(); // expected-note {{in instantiation of 

[clang] [clang][doc] Add documentation for the ASTs used to represent C++ templates (PR #66436)

2023-09-15 Thread Tom Honermann via cfe-commits

tahonermann wrote:

Hi, Scott! It's nice to see you pop up here! :)

I'm a little concerned about maintenance of this documentation going forward. 
As you know, the Clang AST is not intended to be stable and, even though I 
don't expect dramatic changes to how templates are represented, it will take 
some effort to ensure the code and the documentation stay in sync. Do you have 
any thoughts regarding how we can implement an automated process to ensure the 
documentation is updated?

For anyone not familiar, [ded](https://github.com/smcpeak/ded) is a diagram 
editor that Scott developed. I've used it in the past and found it to be 
lightweight and easy to use.

https://github.com/llvm/llvm-project/pull/66436
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 6658db5 - [clang] Fix timing of propagation of MSInheritanceAttr for template instantiation declarations.

2023-08-31 Thread Tom Honermann via cfe-commits

Author: Tom Honermann
Date: 2023-08-31T09:10:05-07:00
New Revision: 6658db5e501475bf288f6d9eb2a8ff21d5fee8b5

URL: 
https://github.com/llvm/llvm-project/commit/6658db5e501475bf288f6d9eb2a8ff21d5fee8b5
DIFF: 
https://github.com/llvm/llvm-project/commit/6658db5e501475bf288f6d9eb2a8ff21d5fee8b5.diff

LOG: [clang] Fix timing of propagation of MSInheritanceAttr for template 
instantiation declarations.

This change addresses three issues:
1) A failure to propagate a MSInheritanceAttr prior to it being required by
   an explicit class template instantiation definition.
2) The same MSInheritanceAttr attribute being attached to the same
   ClassTemplateSpecializationDecl twice.
3) MSInheritanceAttr attributes were not being cloned nor marked as inherited
   when added to new template instantiation declarations.

Sema::ActOnExplicitInstantiation() is responsible for the construction of
ClassTemplateSpecializationDecl nodes for explicit template instantiation
declarations and definitions.  When invoked when a prior declaration node
corresponding to an implicit instantiation exists, the prior declaration
node is repurposed to represent the explicit instantiation declaration
or definition.  When no previous declaration node exists or when the previous
node corresponds to an explicit declaration, a new node is allocated.
Previously, in either case, the function attempted to propagate any existing
MSInheritanceAttr attribute from the previous node, but did so regardless
of whether the previous node was reused (in which case the repurposed previous
node would gain a second attachment of the attribute; the second issue listed
above) or a new node was created.  In the latter case, the attribute was not
propagated before it was required to be present when compiling for C++17 or
later (the first issue listed above).  The absent attribute resulted in an
assertion failure that occurred during instantiation of the specialization
definition when attempting to complete the definition in order to determine
its alignment so as to resolve a lookup for a deallocation function for a
virtual destructor.  This change addresses both issues by propagating the
attribute closer in time to when a new ClassTemplateSpecializationDecl node
is created and only when such a node is newly created.

Reviewed By: aaron.ballman, rnk

Differential Revision: https://reviews.llvm.org/D158869

Added: 


Modified: 
clang/docs/ReleaseNotes.rst
clang/lib/Sema/SemaTemplate.cpp
clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp

Removed: 




diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index ded58a369c7a03..138730336f7426 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -292,6 +292,9 @@ Arm and AArch64 Support
 
 Windows Support
 ^^^
+- Fixed an assertion failure that occurred due to a failure to propagate
+  ``MSInheritanceAttr`` attributes to class template instantiations created
+  for explicit template instantiation declarations.
 
 LoongArch Support
 ^

diff  --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index f45c4c463fa95f..808a8b000aff72 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -10110,6 +10110,17 @@ DeclResult Sema::ActOnExplicitInstantiation(
 ClassTemplate, CanonicalConverted, PrevDecl);
 SetNestedNameSpecifier(*this, Specialization, SS);
 
+// A MSInheritanceAttr attached to the previous declaration must be
+// propagated to the new node prior to instantiation.
+if (PrevDecl) {
+  if (const auto *A = PrevDecl->getAttr()) {
+auto *Clone = A->clone(getASTContext());
+Clone->setInherited(true);
+Specialization->addAttr(Clone);
+Consumer.AssignInheritanceModel(Specialization);
+  }
+}
+
 if (!HasNoEffect && !PrevDecl) {
   // Insert the new specialization.
   ClassTemplate->AddSpecialization(Specialization, InsertPos);
@@ -10226,11 +10237,6 @@ DeclResult Sema::ActOnExplicitInstantiation(
   dllExportImportClassTemplateSpecialization(*this, Def);
 }
 
-if (Def->hasAttr()) {
-  Specialization->addAttr(Def->getAttr());
-  Consumer.AssignInheritanceModel(Specialization);
-}
-
 // Set the template specialization kind. Make sure it is set before
 // instantiating the members which will trigger ASTConsumer callbacks.
 Specialization->setTemplateSpecializationKind(TSK);

diff  --git a/clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp 
b/clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
index 04ce29c64d6e36..2ac1961465d8a8 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - 
-triple=i386-pc-win32 

[clang] a68039c - [Clang] Add tests and mark as implemented WG14-N2728

2023-04-27 Thread Tom Honermann via cfe-commits

Author: Tom Honermann
Date: 2023-04-27T14:25:41-07:00
New Revision: a68039c51e6123bea4a019c02b72297e0de58529

URL: 
https://github.com/llvm/llvm-project/commit/a68039c51e6123bea4a019c02b72297e0de58529
DIFF: 
https://github.com/llvm/llvm-project/commit/a68039c51e6123bea4a019c02b72297e0de58529.diff

LOG: [Clang] Add tests and mark as implemented WG14-N2728

This change expands testing of UTF-8, UTF-16, and UTF-32 character and string
literals as validation that WG14 N2728 (char16_t & char32_t string literals
shall be UTF-16 & UTF-32) has been implemented.

Reviewed By: cor3ntin, aaron.ballman

Differential Revision: https://reviews.llvm.org/D149098

Added: 


Modified: 
clang/test/Lexer/char-literal.cpp
clang/www/c_status.html

Removed: 




diff  --git a/clang/test/Lexer/char-literal.cpp 
b/clang/test/Lexer/char-literal.cpp
index a71500f8f0107..f2d72280e66cd 100644
--- a/clang/test/Lexer/char-literal.cpp
+++ b/clang/test/Lexer/char-literal.cpp
@@ -1,5 +1,8 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 
-Wfour-char-constants -fsyntax-only -verify %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c11 -x c 
-Wfour-char-constants -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 
-Wfour-char-constants -fsyntax-only -verify=cxx,expected %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++17 
-Wfour-char-constants -fsyntax-only -verify=cxx,expected %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++20 
-Wfour-char-constants -fsyntax-only -verify=cxx,expected %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c11 -x c 
-Wfour-char-constants -fsyntax-only -verify=c,expected %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c2x -x c 
-Wfour-char-constants -fsyntax-only -verify=c,expected %s
 
 #ifndef __cplusplus
 typedef __WCHAR_TYPE__ wchar_t;
@@ -38,3 +41,81 @@ char16_t q[2] = u"\U0001";
 #ifdef __cplusplus
 // expected-error@-2 {{too long}}
 #endif
+
+// UTF-8 character literal code point ranges.
+#if __cplusplus >= 201703L || __STDC_VERSION__ >= 201710L
+_Static_assert(u8'\U' == 0x00, ""); // c-error {{universal character 
name refers to a control character}}
+_Static_assert(u8'\U007F' == 0x7F, ""); // c-error {{universal character 
name refers to a control character}}
+_Static_assert(u8'\U0080', ""); // c-error {{universal character name 
refers to a control character}}
+// cxx-error@-1 {{character too large for 
enclosing character literal type}}
+_Static_assert((unsigned char)u8'\xFF' == (unsigned char)0xFF, "");
+#endif
+
+// UTF-8 string literal code point ranges.
+_Static_assert(u8"\U"[0] == 0x00, ""); // c-error {{universal 
character name refers to a control character}}
+_Static_assert(u8"\U007F"[0] == 0x7F, ""); // c-error {{universal 
character name refers to a control character}}
+_Static_assert((unsigned char)u8"\U0080"[0] == (unsigned char)0xC2, ""); 
// c-error {{universal character name refers to a control character}}
+_Static_assert((unsigned char)u8"\U0080"[1] == (unsigned char)0x80, ""); 
// c-error {{universal character name refers to a control character}}
+_Static_assert((unsigned char)u8"\U07FF"[0] == (unsigned char)0xDF, "");
+_Static_assert((unsigned char)u8"\U07FF"[1] == (unsigned char)0xBF, "");
+_Static_assert((unsigned char)u8"\U0800"[0] == (unsigned char)0xE0, "");
+_Static_assert((unsigned char)u8"\U0800"[1] == (unsigned char)0xA0, "");
+_Static_assert((unsigned char)u8"\U0800"[2] == (unsigned char)0x80, "");
+_Static_assert(u8"\UD800"[0], ""); // expected-error {{invalid universal 
character}}
+_Static_assert(u8"\UDFFF"[0], ""); // expected-error {{invalid universal 
character}}
+_Static_assert((unsigned char)u8"\U"[0] == (unsigned char)0xEF, "");
+_Static_assert((unsigned char)u8"\U"[1] == (unsigned char)0xBF, "");
+_Static_assert((unsigned char)u8"\U"[2] == (unsigned char)0xBF, "");
+_Static_assert((unsigned char)u8"\U0001"[0] == (unsigned char)0xF0, "");
+_Static_assert((unsigned char)u8"\U0001"[1] == (unsigned char)0x90, "");
+_Static_assert((unsigned char)u8"\U0001"[2] == (unsigned char)0x80, "");
+_Static_assert((unsigned char)u8"\U0001"[3] == (unsigned char)0x80, "");
+_Static_assert((unsigned char)u8"\U0010"[0] == (unsigned char)0xF4, "");
+_Static_assert((unsigned char)u8"\U0010"[1] == (unsigned char)0x8F, "");
+_Static_assert((unsigned char)u8"\U0010"[2] == (unsigned char)0xBF, "");
+_Static_assert((unsigned char)u8"\U0010"[3] == (unsigned char)0xBF, "");
+_Static_assert(u8"\U0011"[0], ""); // expected-error {{invalid universal 
character}}
+
+#if !defined(__STDC_UTF_16__)
+#error __STDC_UTF_16__ is not defined.
+#endif
+#if __STDC_UTF_16__ != 1
+#error __STDC_UTF_16__ has the wrong value.
+#endif
+
+// UTF-16 character literal code 

[clang] ecd0be1 - [clang] Warn by default that implicit capture of 'this' is deprecated in C++20 and later.

2023-02-02 Thread Tom Honermann via cfe-commits

Author: Tom Honermann
Date: 2023-02-02T15:10:47-05:00
New Revision: ecd0be100bed5bae1f22d3da28bfcca89934af8c

URL: 
https://github.com/llvm/llvm-project/commit/ecd0be100bed5bae1f22d3da28bfcca89934af8c
DIFF: 
https://github.com/llvm/llvm-project/commit/ecd0be100bed5bae1f22d3da28bfcca89934af8c.diff

LOG: [clang] Warn by default that implicit capture of 'this' is deprecated in 
C++20 and later.

Previously, a warning that C++20 deprecated implicit capture of 'this' for
lambda captures specified with a capture default of '=' was only issued when
'-Wdeprecated' or '-Wdeprecated-this-capture' was specified. This change
enables the warning by default (it is still only issued when compiling for
C++20 or later). This is consistent with gcc which warns by default (MSVC
requires '/Wall').

Reviewed By: erichkeane, shafik

Differential Revision: https://reviews.llvm.org/D142639

Added: 
clang/test/SemaCXX/lambda-implicit-this-capture.cpp

Modified: 
clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp
clang/test/SemaCXX/cxx2a-lambda-equals-this.cpp

Removed: 




diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 8e93be1041c3..3f1f492c3ccd 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -70,6 +70,9 @@ Improvements to Clang's diagnostics
 - We now generate a diagnostic for signed integer overflow due to unary minus
   in a non-constant expression context. This fixes
   `Issue 31643 `_
+- Clang now warns by default for C++20 and later about deprecated capture of
+  ``this`` with a capture default of ``=``. This warning can be disabled with
+  ``-Wno-deprecated-this-capture``.
 
 Non-comprehensive list of changes in this release
 -

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 6d6f474f6dcd..7944b868572a 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7906,7 +7906,7 @@ let CategoryName = "Lambda Issue" in {
 "is a C++20 extension">, InGroup;
   def warn_deprecated_this_capture : Warning<
 "implicit capture of 'this' with a capture default of '=' is deprecated">,
-InGroup, DefaultIgnore;
+InGroup;
   def note_deprecated_this_capture : Note<
 "add an explicit capture of 'this' to capture '*this' by reference">;
 

diff  --git a/clang/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp 
b/clang/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp
index 28af62368a89..e9e2ecab8e02 100644
--- a/clang/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp
+++ b/clang/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -emit-llvm-only %s
-// RUN: %clang_cc1 -std=c++2a -verify -verify=expected-cxx2a -fsyntax-only 
-fblocks -emit-llvm-only %s
+// RUN: %clang_cc1 -std=c++2a -verify -verify=expected-cxx2a -fsyntax-only 
-fblocks -emit-llvm-only -Wno-deprecated-this-capture %s
 // RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -emit-llvm-only 
-triple i386-windows-pc %s
-// RUN: %clang_cc1 -std=c++2a -verify -verify=expected-cxx2a -fsyntax-only 
-fblocks -emit-llvm-only -triple i386-windows-pc %s
+// RUN: %clang_cc1 -std=c++2a -verify -verify=expected-cxx2a -fsyntax-only 
-fblocks -emit-llvm-only -triple i386-windows-pc -Wno-deprecated-this-capture %s
 // DONTRUNYET: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks 
-fdelayed-template-parsing %s -DDELAYED_TEMPLATE_PARSING
 // DONTRUNYET: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks 
-fms-extensions %s -DMS_EXTENSIONS
 // DONTRUNYET: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks 
-fdelayed-template-parsing -fms-extensions %s -DMS_EXTENSIONS 
-DDELAYED_TEMPLATE_PARSING

diff  --git a/clang/test/SemaCXX/cxx2a-lambda-equals-this.cpp 
b/clang/test/SemaCXX/cxx2a-lambda-equals-this.cpp
index 652fb8da9b6d..ce6916322e5d 100644
--- a/clang/test/SemaCXX/cxx2a-lambda-equals-this.cpp
+++ b/clang/test/SemaCXX/cxx2a-lambda-equals-this.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -std=c++2a -verify %s -Wdeprecated
+// RUN: %clang_cc1 -std=c++2a -verify %s
+// expected-no-diagnostics
 
 // This test does two things.
 // Deleting the copy constructor ensures that an [=, this] capture doesn't 
copy the object.
@@ -12,12 +13,3 @@ class A {
 L();
   }
 };
-
-struct B {
-  int i;
-  void f() {
-(void) [=] { // expected-note {{add an explicit capture of 'this'}}
-  return i; // expected-warning {{implicit capture of 'this' with a 
capture default of '=' is deprecated}}
-};
-  }
-};

diff  --git a/clang/test/SemaCXX/lambda-implicit-this-capture.cpp 
b/clang/test/SemaCXX/lambda-implicit-this-capture.cpp
new 

[clang] 3b1d455 - [clang] Correct -frewrite-includes generation of line control directives with mixed EOL forms.

2023-01-05 Thread Tom Honermann via cfe-commits

Author: Tom Honermann
Date: 2023-01-05T13:24:01-05:00
New Revision: 3b1d45518910b529104a269d5f6712a720cc3ff7

URL: 
https://github.com/llvm/llvm-project/commit/3b1d45518910b529104a269d5f6712a720cc3ff7
DIFF: 
https://github.com/llvm/llvm-project/commit/3b1d45518910b529104a269d5f6712a720cc3ff7.diff

LOG: [clang] Correct -frewrite-includes generation of line control directives 
with mixed EOL forms.

Previously, if a header file and a source file used different end of line
(EOL) forms, preprocessed output generated with the -frewrite-includes option
would, in some cases, generate line control directives with the wrong line
number due to an error in how source file lines were counted.

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

Reviewed By: cor3ntin

Differential Revision: https://reviews.llvm.org/D140984

Added: 
clang/test/Frontend/rewrite-includes-mixed-eol-crlf.c
clang/test/Frontend/rewrite-includes-mixed-eol-crlf.h
clang/test/Frontend/rewrite-includes-mixed-eol-lf.c
clang/test/Frontend/rewrite-includes-mixed-eol-lf.h

Modified: 
clang/docs/ReleaseNotes.rst
clang/lib/Frontend/Rewrite/InclusionRewriter.cpp

Removed: 




diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index b308dd6c87860..ba464df6c0d3b 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -331,6 +331,10 @@ Bug Fixes
   `Issue 58800 `_
 - Fix an issue that triggers a crash if we instantiate a hidden friend 
functions.
   This fixes `Issue 54457 `_
+- Fix an issue where -frewrite-includes generated line control directives with
+  incorrect line numbers in some cases when a header file used an end of line
+  character sequence that 
diff ered from the primary source file.
+  `Issue 59736 `_
 
 Improvements to Clang's diagnostics
 ^^^

diff  --git a/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp 
b/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
index 810ec680448c5..d3a3db0139c6d 100644
--- a/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
+++ b/clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
@@ -281,27 +281,33 @@ void InclusionRewriter::OutputContentUpTo(const 
MemoryBufferRef ,
 
   StringRef TextToWrite(FromFile.getBufferStart() + WriteFrom,
 WriteTo - WriteFrom);
+  // count lines manually, it's faster than getPresumedLoc()
+  Line += TextToWrite.count(LocalEOL);
 
   if (MainEOL == LocalEOL) {
 OS << TextToWrite;
-// count lines manually, it's faster than getPresumedLoc()
-Line += TextToWrite.count(LocalEOL);
-if (EnsureNewline && !TextToWrite.endswith(LocalEOL))
-  OS << MainEOL;
   } else {
 // Output the file one line at a time, rewriting the line endings as we go.
 StringRef Rest = TextToWrite;
 while (!Rest.empty()) {
-  StringRef LineText;
-  std::tie(LineText, Rest) = Rest.split(LocalEOL);
+  // Identify and output the next line excluding an EOL sequence if 
present.
+  size_t Idx = Rest.find(LocalEOL);
+  StringRef LineText = Rest.substr(0, Idx);
   OS << LineText;
-  Line++;
-  if (!Rest.empty())
+  if (Idx != StringRef::npos) {
+// An EOL sequence was present, output the EOL sequence for the
+// main source file and skip past the local EOL sequence.
 OS << MainEOL;
+Idx += LocalEOL.size();
+  }
+  // Strip the line just handled. If Idx is npos or matches the end of the
+  // text, Rest will be set to an empty string and the loop will terminate.
+  Rest = Rest.substr(Idx);
 }
-if (TextToWrite.endswith(LocalEOL) || EnsureNewline)
-  OS << MainEOL;
   }
+  if (EnsureNewline && !TextToWrite.endswith(LocalEOL))
+OS << MainEOL;
+
   WriteFrom = WriteTo;
 }
 

diff  --git a/clang/test/Frontend/rewrite-includes-mixed-eol-crlf.c 
b/clang/test/Frontend/rewrite-includes-mixed-eol-crlf.c
new file mode 100644
index 0..d672c0667
--- /dev/null
+++ b/clang/test/Frontend/rewrite-includes-mixed-eol-crlf.c
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -E -frewrite-includes %s | %clang_cc1 -
+// expected-no-diagnostics
+// Note: This source file has CRLF line endings.
+// This test validates that -frewrite-includes translates the end of line (EOL)
+// form used in header files to the EOL form used in the the primary source
+// file when the files use 
diff erent EOL forms.
+#include "rewrite-includes-mixed-eol-crlf.h"
+#include "rewrite-includes-mixed-eol-lf.h"

diff  --git a/clang/test/Frontend/rewrite-includes-mixed-eol-crlf.h 
b/clang/test/Frontend/rewrite-includes-mixed-eol-crlf.h
new file mode 100644
index 0..0439b88b75e2c
--- /dev/null
+++ b/clang/test/Frontend/rewrite-includes-mixed-eol-crlf.h
@@ -0,0 +1,11 @@
+// 

[clang] 3e25ae6 - [Clang] Correct when Itanium ABI guard variables are set for non-block variables with static or thread storage duration.

2022-11-16 Thread Tom Honermann via cfe-commits

Author: Tom Honermann
Date: 2022-11-16T16:31:35-05:00
New Revision: 3e25ae605edd88720de3a4407fdd4ea85f758dce

URL: 
https://github.com/llvm/llvm-project/commit/3e25ae605edd88720de3a4407fdd4ea85f758dce
DIFF: 
https://github.com/llvm/llvm-project/commit/3e25ae605edd88720de3a4407fdd4ea85f758dce.diff

LOG: [Clang] Correct when Itanium ABI guard variables are set for non-block 
variables with static or thread storage duration.

Previously, Itanium ABI guard variables were set after initialization was
complete for non-block declared variables with static and thread storage
duration. That resulted in initialization of such variables being restarted
in cases where the variable was referenced while it was still under
construction. Per C++20 [class.cdtor]p2, such references are permitted
(though the value obtained by such an access is unspecified). The late
initialization resulted in recursive reinitialization loops for cases like
this:
  template
  struct ct {
struct mc {
  mc() { ct::smf(); }
  void mf() const {}
};
thread_local static mc tlsdm;
static void smf() { tlsdm.mf(); }
  };
  template
  thread_local typename ct::mc ct::tlsdm;
  int main() {
ct::smf();
  }

With this change, guard variables are set before initialization is started
so as to avoid such reinitialization loops.

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

Reviewed By: rjmccall

Differential Revision: https://reviews.llvm.org/D135919

Added: 


Modified: 
clang/lib/CodeGen/ItaniumCXXABI.cpp
clang/test/CodeGenCXX/aix-static-init-temp-spec-and-inline-var.cpp
clang/test/CodeGenCXX/cxx11-thread-local.cpp
clang/test/CodeGenCXX/cxx1y-variable-template.cpp
clang/test/CodeGenCXX/global-init.cpp
clang/test/CodeGenCXX/static-data-member.cpp
clang/test/OpenMP/threadprivate_codegen.cpp

Removed: 




diff  --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp 
b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 5f7c739a76786..20aa9698dc564 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -2485,6 +2485,21 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction ,
 CGF.EmitBlock(InitCheckBlock);
   }
 
+  // The semantics of dynamic initialization of variables with static or thread
+  // storage duration depends on whether they are declared at block-scope. The
+  // initialization of such variables at block-scope can be aborted with an
+  // exception and later retried (per C++20 [stmt.dcl]p4), and recursive entry
+  // to their initialization has undefined behavior (also per C++20
+  // [stmt.dcl]p4). For such variables declared at non-block scope, exceptions
+  // lead to termination (per C++20 [except.terminate]p1), and recursive
+  // references to the variables are governed only by the lifetime rules (per
+  // C++20 [class.cdtor]p2), which means such references are perfectly fine as
+  // long as they avoid touching memory. As a result, block-scope variables 
must
+  // not be marked as initialized until after initialization completes (unless
+  // the mark is reverted following an exception), but non-block-scope 
variables
+  // must be marked prior to initialization so that recursive accesses during
+  // initialization do not restart initialization.
+
   // Variables used when coping with thread-safe statics and exceptions.
   if (threadsafe) {
 // Call __cxa_guard_acquire.
@@ -2500,6 +2515,12 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction ,
 CGF.EHStack.pushCleanup(EHCleanup, guard);
 
 CGF.EmitBlock(InitBlock);
+  } else if (!D.isLocalVarDecl()) {
+// For non-local variables, store 1 into the first byte of the guard
+// variable before the object initialization begins so that references
+// to the variable during initialization don't restart initialization.
+Builder.CreateStore(llvm::ConstantInt::get(CGM.Int8Ty, 1),
+Builder.CreateElementBitCast(guardAddr, CGM.Int8Ty));
   }
 
   // Emit the initializer and add a global destructor if appropriate.
@@ -2512,9 +2533,10 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction ,
 // Call __cxa_guard_release.  This cannot throw.
 CGF.EmitNounwindRuntimeCall(getGuardReleaseFn(CGM, guardPtrTy),
 guardAddr.getPointer());
-  } else {
-// Store 1 into the first byte of the guard variable after initialization 
is
-// complete.
+  } else if (D.isLocalVarDecl()) {
+// For local variables, store 1 into the first byte of the guard variable
+// after the object initialization completes so that initialization is
+// retried if initialization is interrupted by an exception.
 Builder.CreateStore(llvm::ConstantInt::get(CGM.Int8Ty, 1),
 Builder.CreateElementBitCast(guardAddr, CGM.Int8Ty));
   }

diff  --git 
a/clang/test/CodeGenCXX/aix-static-init-temp-spec-and-inline-var.cpp 

[clang] 0982db1 - [Clang] reject bit-fields as instruction operands in Microsoft style inline asm blocks.

2022-10-10 Thread Tom Honermann via cfe-commits

Author: Tom Honermann
Date: 2022-10-10T15:45:02-04:00
New Revision: 0982db188b661d6744b06244fda64d43dd80206e

URL: 
https://github.com/llvm/llvm-project/commit/0982db188b661d6744b06244fda64d43dd80206e
DIFF: 
https://github.com/llvm/llvm-project/commit/0982db188b661d6744b06244fda64d43dd80206e.diff

LOG: [Clang] reject bit-fields as instruction operands in Microsoft style 
inline asm blocks.

MSVC allows bit-fields to be specified as instruction operands in inline asm
blocks. Such references are resolved to the address of the allocation unit that
the named bitfield is a part of. The result is that reads and writes of such
operands will read or mutate nearby bit-fields stored in the same allocation
unit. This is a surprising behavior for which MSVC issues warning C4401,
"'': member is bit field". Intel's icc compiler also allows such
bit-field references, but does not issue a diagnostic.

Prior to this change, Clang fails the following assertion when a bit-field is
referenced in such instructions:
  clang/lib/CodeGen/CGValue.h:338: llvm::Value* 
clang::CodeGen::LValue::getPointer(clang::CodeGen::CodeGenFunction&) const: 
Assertion `isSimple()' failed.
In non-assert enabled builds, Clang's behavior appears to match the behavior
of the MSVC and icc compilers, though it is unknown if that is by design or
happenstance.

Following this change, attempts to use a bit-field as an instruction operand
in Microsoft style asm blocks is diagnosed as an error due to the risk of
unintentionally reading or writing nearby bit-fields.

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

Reviewed By: erichkeane, aaron.ballman

Differential Revision: https://reviews.llvm.org/D135500

Added: 


Modified: 
clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/DiagnosticCommonKinds.td
clang/lib/Sema/SemaStmtAsm.cpp
clang/test/Parser/ms-inline-asm.c

Removed: 




diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 29550f5376a7f..9803243e61967 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -140,6 +140,25 @@ code bases.
   *p; // Now diagnosed as a warning-as-error.
 }
 
+- Clang now diagnoses use of a bit-field as an instruction operand in Microsoft
+  style inline asm blocks as an error. Previously, a bit-field operand yielded
+  the address of the allocation unit the bit-field was stored within; reads or
+  writes therefore had the potential to read or write nearby bit-fields. This
+  change fixes `issue 57791 
`_.
+
+  .. code-block:: c++
+
+typedef struct S {
+  unsigned bf:1;
+} S;
+void f(S s) {
+  __asm {
+mov eax, s.bf // Now diagnosed as an error.
+mov s.bf, eax // Now diagnosed as an error.
+  }
+}
+
+
 What's New in Clang |release|?
 ==
 Some of the major new features and improvements to Clang are listed

diff  --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td 
b/clang/include/clang/Basic/DiagnosticCommonKinds.td
index 39dee7e683ff9..e0408e9abd2e7 100644
--- a/clang/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td
@@ -279,6 +279,9 @@ let CategoryName = "Inline Assembly Issue" in {
   def err_asm_invalid_type : Error<
 "invalid type %0 in asm %select{input|output}1">;
 
+  def err_ms_asm_bitfield_unsupported : Error<
+"an inline asm block cannot have an operand which is a bit-field">;
+
   def warn_stack_clash_protection_inline_asm : Warning<
 "Unable to protect inline asm that clobbers stack pointer against stack 
clash">,
 InGroup>;

diff  --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp
index 715b5e314d90b..d19f4d6c78356 100644
--- a/clang/lib/Sema/SemaStmtAsm.cpp
+++ b/clang/lib/Sema/SemaStmtAsm.cpp
@@ -932,13 +932,24 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, 
SourceLocation LBraceLoc,
   bool IsSimple = (NumOutputs != 0 || NumInputs != 0);
   setFunctionHasBranchProtectedScope();
 
+  bool InvalidOperand = false;
   for (uint64_t I = 0; I < NumOutputs + NumInputs; ++I) {
-if (Exprs[I]->getType()->isBitIntType())
-  return StmtError(
-  Diag(Exprs[I]->getBeginLoc(), diag::err_asm_invalid_type)
-  << Exprs[I]->getType() << (I < NumOutputs)
-  << Exprs[I]->getSourceRange());
+Expr *E = Exprs[I];
+if (E->getType()->isBitIntType()) {
+  InvalidOperand = true;
+  Diag(E->getBeginLoc(), diag::err_asm_invalid_type)
+  << E->getType() << (I < NumOutputs)
+  << E->getSourceRange();
+} else if (E->refersToBitField()) {
+  InvalidOperand = true;
+  FieldDecl *BitField = E->getSourceBitField();
+  Diag(E->getBeginLoc(), diag::err_ms_asm_bitfield_unsupported)
+  << E->getSourceRange();
+  Diag(BitField->getLocation(), 

[clang] 4409a83 - [clang] Correct handling of lambdas in lambda default arguments in dependent contexts.

2022-10-04 Thread Tom Honermann via cfe-commits

Author: Tom Honermann
Date: 2022-10-04T09:04:54-07:00
New Revision: 4409a83c293537e22da046b54e9f69454cdd3dca

URL: 
https://github.com/llvm/llvm-project/commit/4409a83c293537e22da046b54e9f69454cdd3dca
DIFF: 
https://github.com/llvm/llvm-project/commit/4409a83c293537e22da046b54e9f69454cdd3dca.diff

LOG: [clang] Correct handling of lambdas in lambda default arguments in 
dependent contexts.

Previously, a lambda expression in a dependent context with a default argument
containing an immediately invoked lambda expression would produce a closure
class object that, if invoked such that the default argument was used, resulted
in a compiler crash or one of the following assertion failures during code
generation. The failures occurred regardless of whether the lambda expressions
were dependent.

  clang/lib/CodeGen/CGCall.cpp:
  Assertion `(isGenericMethod || Ty->isVariablyModifiedType() || 
Ty.getNonReferenceType()->isObjCRetainableType() || getContext() 
.getCanonicalType(Ty.getNonReferenceType()) .getTypePtr() == 
getContext().getCanonicalType((*Arg)->getType()).getTypePtr()) && "type 
mismatch in call argument!"' failed.

  clang/lib/AST/Decl.cpp:
  Assertion `!Init->isValueDependent()' failed.

Default arguments in declarations in local context are instantiated along with
their enclosing function or variable template (since such declarations can't
be explicitly specialized). Previously, such instantiations were performed at
the same time that their associated parameters were instantiated. However, that
approach fails in cases like the following in which the context for the inner
lambda is the outer lambda, but construction of the outer lambda is dependent
on the parameters of the inner lambda. This change resolves this dependency by
delyaing instantiation of default arguments in local contexts until after
construction of the enclosing context.
  template 
  auto f() {
return [](T = []{ return T{}; }()) { return 0; };
  }

Refactoring included with this change results in the same code now being used
to instantiate default arguments that appear in local context and those that
are only instantiated when used at a call site; previously, such code was
duplicated and out of sync.

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

Reviewed By: erichkeane

Differential Revision: https://reviews.llvm.org/D133500

Added: 
clang/test/CodeGenCXX/mangle-lambdas-cxx14.cpp
clang/test/CodeGenCXX/mangle-lambdas-cxx20.cpp

Modified: 
clang/include/clang/Sema/Sema.h
clang/lib/AST/DeclBase.cpp
clang/lib/Sema/SemaTemplateInstantiate.cpp
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
clang/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp
clang/test/CodeGenCXX/mangle-lambdas.cpp
clang/test/SemaCXX/vartemplate-lambda.cpp
clang/test/SemaTemplate/default-arguments.cpp
clang/test/SemaTemplate/instantiate-local-class.cpp

Removed: 




diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 74735fb8d07c1..ce6f67ad19af6 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9782,6 +9782,9 @@ class Sema final {
   SmallVectorImpl ,
   SmallVectorImpl *OutParams,
   ExtParameterInfoBuilder );
+  bool SubstDefaultArgument(SourceLocation Loc, ParmVarDecl *Param,
+const MultiLevelTemplateArgumentList ,
+bool ForCallExpr = false);
   ExprResult SubstExpr(Expr *E,
const MultiLevelTemplateArgumentList );
 

diff  --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index a9ac441092be0..763fc1d9f17fb 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -261,12 +261,12 @@ const TemplateParameterList 
*Decl::getDescribedTemplateParams() const {
 
 bool Decl::isTemplated() const {
   // A declaration is templated if it is a template or a template pattern, or
-  // is within (lexcially for a friend, semantically otherwise) a dependent
-  // context.
-  // FIXME: Should local extern declarations be treated like friends?
+  // is within (lexcially for a friend or local function declaration,
+  // semantically otherwise) a dependent context.
   if (auto *AsDC = dyn_cast(this))
 return AsDC->isDependentContext();
-  auto *DC = getFriendObjectKind() ? getLexicalDeclContext() : 
getDeclContext();
+  auto *DC = getFriendObjectKind() || isLocalExternDecl()
+  ? getLexicalDeclContext() : getDeclContext();
   return DC->isDependentContext() || isTemplateDecl() ||
  getDescribedTemplateParams();
 }

diff  --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp 
b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index c6eb034e43708..21b141f96a695 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -179,11 +179,11 @@ 

[clang] 4247cdb - [clang]: Add DeclContext::dumpAsDecl().

2022-10-03 Thread Tom Honermann via cfe-commits

Author: Tom Honermann
Date: 2022-10-03T17:25:44-04:00
New Revision: 4247cdb568eca4c31b14d91105fe5ee140225036

URL: 
https://github.com/llvm/llvm-project/commit/4247cdb568eca4c31b14d91105fe5ee140225036
DIFF: 
https://github.com/llvm/llvm-project/commit/4247cdb568eca4c31b14d91105fe5ee140225036.diff

LOG: [clang]: Add DeclContext::dumpAsDecl().

This change enables a declaration to be conveniently displayed within
a debugger when only a pointer to its DeclContext is available. For example,
in gdb:
  (gdb) p Ctx
  $1 = (const clang::DeclContext *) 0x14c1a580
  (gdb) p Ctx->dumpAsDecl()
  ClassTemplateSpecializationDecl 0x14c1a540  line:2:8 
struct ct
  `-TemplateArgument type 'int'
`-BuiltinType 0x14bac420 'int'
  $2 = void

In the event that the pointed to DeclContext is invalid (that it has an
invalid DeclKind as a result of a dangling pointer, memory corruption, etc...)
it is not possible to dump its associated declaration. In this case, the
DeclContext will be reported as invalid. For example, in gdb:
  (gdb) p Ctx->dumpAsDecl()
  DeclContext 0x14c1a580 
  $3 = void

Added: 


Modified: 
clang/include/clang/AST/ASTDumper.h
clang/include/clang/AST/DeclBase.h
clang/lib/AST/ASTDumper.cpp
clang/lib/AST/DeclBase.cpp

Removed: 




diff  --git a/clang/include/clang/AST/ASTDumper.h 
b/clang/include/clang/AST/ASTDumper.h
index a154bc2db3a7..71ac467e5104 100644
--- a/clang/include/clang/AST/ASTDumper.h
+++ b/clang/include/clang/AST/ASTDumper.h
@@ -32,6 +32,7 @@ class ASTDumper : public ASTNodeTraverser {
 
   TextNodeDumper () { return NodeDumper; }
 
+  void dumpInvalidDeclContext(const DeclContext *DC);
   void dumpLookups(const DeclContext *DC, bool DumpDecls);
 
   template 

diff  --git a/clang/include/clang/AST/DeclBase.h 
b/clang/include/clang/AST/DeclBase.h
index 1332b00232be..8a5f75573095 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -1909,6 +1909,10 @@ class DeclContext {
 public:
   ~DeclContext();
 
+  // For use when debugging; hasValidDeclKind() will always return true for
+  // a correctly constructed object within its lifetime.
+  bool hasValidDeclKind() const;
+
   Decl::Kind getDeclKind() const {
 return static_cast(DeclContextBits.DeclKind);
   }
@@ -2530,6 +2534,8 @@ class DeclContext {
   static bool classof(const Decl *D);
   static bool classof(const DeclContext *D) { return true; }
 
+  void dumpAsDecl() const;
+  void dumpAsDecl(const ASTContext *Ctx) const;
   void dumpDeclContext() const;
   void dumpLookups() const;
   void dumpLookups(llvm::raw_ostream , bool DumpDecls = false,

diff  --git a/clang/lib/AST/ASTDumper.cpp b/clang/lib/AST/ASTDumper.cpp
index 60700f71c4b9..9900efb5a48d 100644
--- a/clang/lib/AST/ASTDumper.cpp
+++ b/clang/lib/AST/ASTDumper.cpp
@@ -19,9 +19,37 @@
 #include "clang/Basic/Module.h"
 #include "clang/Basic/SourceManager.h"
 #include "llvm/Support/raw_ostream.h"
+
 using namespace clang;
 using namespace clang::comments;
 
+void ASTDumper::dumpInvalidDeclContext(const DeclContext *DC) {
+  NodeDumper.AddChild([=] {
+if (!DC) {
+  ColorScope Color(OS, ShowColors, NullColor);
+  OS << "<<>>";
+  return;
+}
+// An invalid DeclContext is one for which a dyn_cast() from a DeclContext
+// pointer to a Decl pointer would fail an assertion or otherwise fall prey
+// to undefined behavior as a result of an invalid associated DeclKind.
+// Such invalidity is not supposed to happen of course, but, when it does,
+// the information provided below is intended to provide some hints about
+// what might have gone awry.
+{
+  ColorScope Color(OS, ShowColors, DeclKindNameColor);
+  OS << "DeclContext";
+}
+NodeDumper.dumpPointer(DC);
+OS << " <";
+{
+  ColorScope Color(OS, ShowColors, DeclNameColor);
+  OS << "unrecognized Decl kind " << (unsigned)DC->getDeclKind();
+}
+OS << ">";
+  });
+}
+
 void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) {
   NodeDumper.AddChild([=] {
 OS << "StoredDeclsMap ";
@@ -200,6 +228,31 @@ LLVM_DUMP_METHOD void Decl::dumpColor() const {
   P.Visit(this);
 }
 
+LLVM_DUMP_METHOD void DeclContext::dumpAsDecl() const {
+  dumpAsDecl(nullptr);
+}
+
+LLVM_DUMP_METHOD void DeclContext::dumpAsDecl(const ASTContext *Ctx) const {
+  // By design, DeclContext is required to be a base class of some class that
+  // derives from Decl. Thus, it should always be possible to dyn_cast() from
+  // a DeclContext pointer to a Decl pointer and Decl::castFromDeclContext()
+  // asserts that to be the case. Since this function is intended for use in a
+  // debugger, it performs an additional check in order to prevent a failed
+  // cast and assertion. If that check fails, then the (invalid) DeclContext
+  // is dumped with an indication of its invalidity.
+  if (hasValidDeclKind()) {
+const auto *D = 

[clang] 8d03328 - [clang] NFC: Add a missing const qualifier to Decl::isLocalExternDecl().

2022-09-08 Thread Tom Honermann via cfe-commits

Author: Tom Honermann
Date: 2022-09-08T13:21:10-07:00
New Revision: 8d03328e7be4778f8b5d5f3ea2f77b1f8b8ea38a

URL: 
https://github.com/llvm/llvm-project/commit/8d03328e7be4778f8b5d5f3ea2f77b1f8b8ea38a
DIFF: 
https://github.com/llvm/llvm-project/commit/8d03328e7be4778f8b5d5f3ea2f77b1f8b8ea38a.diff

LOG: [clang] NFC: Add a missing const qualifier to Decl::isLocalExternDecl().

Added: 


Modified: 
clang/include/clang/AST/DeclBase.h

Removed: 




diff  --git a/clang/include/clang/AST/DeclBase.h 
b/clang/include/clang/AST/DeclBase.h
index 1c4e726817bb..328d28c08bcc 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -1128,7 +1128,7 @@ class alignas(8) Decl {
   /// Determine whether this is a block-scope declaration with linkage.
   /// This will either be a local variable declaration declared 'extern', or a
   /// local function declaration.
-  bool isLocalExternDecl() {
+  bool isLocalExternDecl() const {
 return IdentifierNamespace & IDNS_LocalExtern;
   }
 



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


[clang] 5531aba - [clang] Corrections for target_clones multiversion functions.

2022-04-05 Thread Tom Honermann via cfe-commits

Author: Tom Honermann
Date: 2022-04-05T19:50:22-04:00
New Revision: 5531abaf7158652bf7411937781780e9f6358ecf

URL: 
https://github.com/llvm/llvm-project/commit/5531abaf7158652bf7411937781780e9f6358ecf
DIFF: 
https://github.com/llvm/llvm-project/commit/5531abaf7158652bf7411937781780e9f6358ecf.diff

LOG: [clang] Corrections for target_clones multiversion functions.

This change merges code for emit of target and target_clones multiversion
resolver functions and, in doing so, corrects handling of target_clones
functions that are declared but not defined. Previously, a use of such
a target_clones function would result in an attempted emit of an ifunc
that referenced an undefined resolver function. Ifunc references to
undefined resolver functions are not allowed and, when the LLVM verifier
is not disabled (via '-disable-llvm-verifier'), resulted in the verifier
issuing a "IFunc resolver must be a definition" error and aborting the
compilation. With this change, ifuncs and resolver function definitions
are always emitted for used target_clones functions regardless of whether
the target_clones function is defined (if the function is defined, then
the ifunc and resolver are emitted regardless of whether the function is
used).

This change has the side effect of causing target_clones variants and
resolver functions to be emitted in a different order than they were
previously. This is harmless and is reflected in the updated tests.

Reviewed By: erichkeane

Differential Revision: https://reviews.llvm.org/D122958

Added: 


Modified: 
clang/lib/CodeGen/CodeGenModule.cpp
clang/lib/CodeGen/CodeGenModule.h
clang/test/CodeGen/attr-target-clones.c
clang/test/CodeGenCXX/attr-target-clones.cpp

Removed: 




diff  --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index c8770d91e0686..26957ea0768e7 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -3320,13 +3320,13 @@ void 
CodeGenModule::EmitMultiVersionFunctionDefinition(GlobalDecl GD,
 auto *Spec = FD->getAttr();
 for (unsigned I = 0; I < Spec->cpus_size(); ++I)
   EmitGlobalFunctionDefinition(GD.getWithMultiVersionIndex(I), nullptr);
-// Requires multiple emits.
   } else if (FD->isTargetClonesMultiVersion()) {
 auto *Clone = FD->getAttr();
 for (unsigned I = 0; I < Clone->featuresStrs_size(); ++I)
   if (Clone->isFirstOfVersion(I))
 EmitGlobalFunctionDefinition(GD.getWithMultiVersionIndex(I), nullptr);
-EmitTargetClonesResolver(GD);
+// Ensure that the resolver function is also emitted.
+GetOrCreateMultiVersionResolver(GD);
   } else
 EmitGlobalFunctionDefinition(GD, GV);
 }
@@ -3408,57 +3408,6 @@ llvm::GlobalValue::LinkageTypes 
getMultiversionLinkage(CodeGenModule ,
   return llvm::GlobalValue::WeakODRLinkage;
 }
 
-void CodeGenModule::EmitTargetClonesResolver(GlobalDecl GD) {
-  const auto *FD = cast(GD.getDecl());
-  assert(FD && "Not a FunctionDecl?");
-  const auto *TC = FD->getAttr();
-  assert(TC && "Not a target_clones Function?");
-
-  llvm::Function *ResolverFunc;
-  if (getTarget().supportsIFunc()) {
-auto *IFunc = cast(GetOrCreateMultiVersionResolver(GD));
-ResolverFunc = cast(IFunc->getResolver());
-  } else
-ResolverFunc = cast(GetOrCreateMultiVersionResolver(GD));
-
-  SmallVector Options;
-  for (unsigned VersionIndex = 0; VersionIndex < TC->featuresStrs_size();
-   ++VersionIndex) {
-if (!TC->isFirstOfVersion(VersionIndex))
-  continue;
-StringRef Version = TC->getFeatureStr(VersionIndex);
-StringRef MangledName =
-getMangledName(GD.getWithMultiVersionIndex(VersionIndex));
-llvm::Constant *Func = GetGlobalValue(MangledName);
-assert(Func &&
-   "Should have already been created before calling resolver emit");
-
-StringRef Architecture;
-llvm::SmallVector Feature;
-
-if (Version.startswith("arch="))
-  Architecture = Version.drop_front(sizeof("arch=") - 1);
-else if (Version != "default")
-  Feature.push_back(Version);
-
-Options.emplace_back(cast(Func), Architecture, Feature);
-  }
-
-  if (supportsCOMDAT())
-ResolverFunc->setComdat(
-getModule().getOrInsertComdat(ResolverFunc->getName()));
-
-  const TargetInfo  = getTarget();
-  std::stable_sort(
-  Options.begin(), Options.end(),
-  [](const CodeGenFunction::MultiVersionResolverOption ,
-const CodeGenFunction::MultiVersionResolverOption ) {
-return TargetMVPriority(TI, LHS) > TargetMVPriority(TI, RHS);
-  });
-  CodeGenFunction CGF(*this);
-  CGF.EmitMultiVersionResolver(ResolverFunc, Options);
-}
-
 void CodeGenModule::emitMultiVersionFunctions() {
   std::vector MVFuncsToEmit;
   MultiVersionFuncs.swap(MVFuncsToEmit);
@@ -3495,26 +3444,58 @@ void CodeGenModule::emitMultiVersionFunctions() {
 Options.emplace_back(cast(Func),
  

[clang] 40af8df - [clang] NFC: Preparation for merging code to emit target and target_clones resolvers.

2022-04-05 Thread Tom Honermann via cfe-commits

Author: Tom Honermann
Date: 2022-04-05T19:50:22-04:00
New Revision: 40af8df6fe642749f9ac5486822c2bd5cc587ab7

URL: 
https://github.com/llvm/llvm-project/commit/40af8df6fe642749f9ac5486822c2bd5cc587ab7
DIFF: 
https://github.com/llvm/llvm-project/commit/40af8df6fe642749f9ac5486822c2bd5cc587ab7.diff

LOG: [clang] NFC: Preparation for merging code to emit target and target_clones 
resolvers.

This change modifies CodeGenModule::emitMultiVersionFunctions() in preparation
for a change that will merge support for emitting target_clones resolvers into
this function. This change mostly serves to isolate indentation changes from
later behavior modifying changes.

Reviewed By: erichkeane

Differential Revision: https://reviews.llvm.org/D122957

Added: 


Modified: 
clang/lib/CodeGen/CodeGenModule.cpp

Removed: 




diff  --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index 5dec1362bc716..c8770d91e0686 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -3463,35 +3463,42 @@ void CodeGenModule::emitMultiVersionFunctions() {
   std::vector MVFuncsToEmit;
   MultiVersionFuncs.swap(MVFuncsToEmit);
   for (GlobalDecl GD : MVFuncsToEmit) {
+const auto *FD = cast(GD.getDecl());
+assert(FD && "Expected a FunctionDecl");
+
 SmallVector Options;
-const FunctionDecl *FD = cast(GD.getDecl());
-getContext().forEachMultiversionedFunctionVersion(
-FD, [this, , ](const FunctionDecl *CurFD) {
-  GlobalDecl CurGD{
-  (CurFD->isDefined() ? CurFD->getDefinition() : CurFD)};
-  StringRef MangledName = getMangledName(CurGD);
-  llvm::Constant *Func = GetGlobalValue(MangledName);
-  if (!Func) {
-if (CurFD->isDefined()) {
-  EmitGlobalFunctionDefinition(CurGD, nullptr);
-  Func = GetGlobalValue(MangledName);
-} else {
-  const CGFunctionInfo  =
-  getTypes().arrangeGlobalDeclaration(GD);
-  llvm::FunctionType *Ty = getTypes().GetFunctionType(FI);
-  Func = GetAddrOfFunction(CurGD, Ty, /*ForVTable=*/false,
-   /*DontDefer=*/false, ForDefinition);
+if (FD->isTargetMultiVersion()) {
+  getContext().forEachMultiversionedFunctionVersion(
+  FD, [this, , ](const FunctionDecl *CurFD) {
+GlobalDecl CurGD{
+(CurFD->isDefined() ? CurFD->getDefinition() : CurFD)};
+StringRef MangledName = getMangledName(CurGD);
+llvm::Constant *Func = GetGlobalValue(MangledName);
+if (!Func) {
+  if (CurFD->isDefined()) {
+EmitGlobalFunctionDefinition(CurGD, nullptr);
+Func = GetGlobalValue(MangledName);
+  } else {
+const CGFunctionInfo  =
+getTypes().arrangeGlobalDeclaration(GD);
+llvm::FunctionType *Ty = getTypes().GetFunctionType(FI);
+Func = GetAddrOfFunction(CurGD, Ty, /*ForVTable=*/false,
+ /*DontDefer=*/false, ForDefinition);
+  }
+  assert(Func && "This should have just been created");
 }
-assert(Func && "This should have just been created");
-  }
 
-  const auto *TA = CurFD->getAttr();
-  llvm::SmallVector Feats;
-  TA->getAddedFeatures(Feats);
+const auto *TA = CurFD->getAttr();
+llvm::SmallVector Feats;
+TA->getAddedFeatures(Feats);
 
-  Options.emplace_back(cast(Func),
-   TA->getArchitecture(), Feats);
-});
+Options.emplace_back(cast(Func),
+ TA->getArchitecture(), Feats);
+  });
+} else {
+  assert(0 && "Expected a target multiversion function");
+  continue;
+}
 
 llvm::Function *ResolverFunc;
 const TargetInfo  = getTarget();



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


[clang] 0ace010 - [clang] NFC: Simplify the interface to CodeGenModule::GetOrCreateMultiVersionResolver().

2022-04-05 Thread Tom Honermann via cfe-commits

Author: Tom Honermann
Date: 2022-04-05T19:50:22-04:00
New Revision: 0ace0100aec31bdff7e856df806cca18d8faabd7

URL: 
https://github.com/llvm/llvm-project/commit/0ace0100aec31bdff7e856df806cca18d8faabd7
DIFF: 
https://github.com/llvm/llvm-project/commit/0ace0100aec31bdff7e856df806cca18d8faabd7.diff

LOG: [clang] NFC: Simplify the interface to 
CodeGenModule::GetOrCreateMultiVersionResolver().

Previously, GetOrCreateMultiVersionResolver() required the caller to provide
a GlobalDecl along with an llvm::type and FunctionDecl. The latter two can be
cheaply obtained from the first, and the llvm::type parameter is not always
used, so requiring the caller to provide them was unnecessary and created the
possibility that callers would pass an inconsistent set. This change simplifies
the interface to only require the GlobalDecl value.

Reviewed By: erichkeane

Differential Revision: https://reviews.llvm.org/D122956

Added: 


Modified: 
clang/lib/CodeGen/CodeGenModule.cpp
clang/lib/CodeGen/CodeGenModule.h

Removed: 




diff  --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index 72fea25a28cfb..5dec1362bc716 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -3414,22 +3414,12 @@ void CodeGenModule::EmitTargetClonesResolver(GlobalDecl 
GD) {
   const auto *TC = FD->getAttr();
   assert(TC && "Not a target_clones Function?");
 
-  QualType CanonTy = Context.getCanonicalType(FD->getType());
-  llvm::Type *DeclTy = getTypes().ConvertType(CanonTy);
-
-  if (const auto *CXXFD = dyn_cast(FD)) {
-const CGFunctionInfo  = 
getTypes().arrangeCXXMethodDeclaration(CXXFD);
-DeclTy = getTypes().GetFunctionType(FInfo);
-  }
-
   llvm::Function *ResolverFunc;
   if (getTarget().supportsIFunc()) {
-auto *IFunc = cast(
-GetOrCreateMultiVersionResolver(GD, DeclTy, FD));
+auto *IFunc = cast(GetOrCreateMultiVersionResolver(GD));
 ResolverFunc = cast(IFunc->getResolver());
   } else
-ResolverFunc =
-cast(GetOrCreateMultiVersionResolver(GD, DeclTy, FD));
+ResolverFunc = cast(GetOrCreateMultiVersionResolver(GD));
 
   SmallVector Options;
   for (unsigned VersionIndex = 0; VersionIndex < TC->featuresStrs_size();
@@ -3545,12 +3535,9 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl 
GD) {
   assert(FD->isCPUDispatchMultiVersion() && "Not a multiversion function?");
   const auto *DD = FD->getAttr();
   assert(DD && "Not a cpu_dispatch Function?");
-  llvm::Type *DeclTy = getTypes().ConvertType(FD->getType());
 
-  if (const auto *CXXFD = dyn_cast(FD)) {
-const CGFunctionInfo  = 
getTypes().arrangeCXXMethodDeclaration(CXXFD);
-DeclTy = getTypes().GetFunctionType(FInfo);
-  }
+  const CGFunctionInfo  = getTypes().arrangeGlobalDeclaration(GD);
+  llvm::FunctionType *DeclTy = getTypes().GetFunctionType(FI);
 
   StringRef ResolverName = getMangledName(GD);
   UpdateMultiVersionNames(GD, FD, ResolverName);
@@ -3640,8 +3627,7 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl 
GD) {
 
   if (getTarget().supportsIFunc()) {
 llvm::GlobalValue::LinkageTypes Linkage = getMultiversionLinkage(*this, 
GD);
-auto *IFunc = cast(
-GetOrCreateMultiVersionResolver(GD, DeclTy, FD));
+auto *IFunc = cast(GetOrCreateMultiVersionResolver(GD));
 
 // Fix up function declarations that were created for cpu_specific before
 // cpu_dispatch was known
@@ -3668,8 +3654,10 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl 
GD) {
 
 /// If a dispatcher for the specified mangled name is not in the module, create
 /// and return an llvm Function with the specified type.
-llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(
-GlobalDecl GD, llvm::Type *DeclTy, const FunctionDecl *FD) {
+llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
+  const auto *FD = cast(GD.getDecl());
+  assert(FD && "Not a FunctionDecl?");
+
   std::string MangledName =
   getMangledNameImpl(*this, GD, FD, /*OmitMultiVersionMangling=*/true);
 
@@ -3685,6 +3673,9 @@ llvm::Constant 
*CodeGenModule::GetOrCreateMultiVersionResolver(
   if (llvm::GlobalValue *ResolverGV = GetGlobalValue(ResolverName))
 return ResolverGV;
 
+  const CGFunctionInfo  = getTypes().arrangeGlobalDeclaration(GD);
+  llvm::FunctionType *DeclTy = getTypes().GetFunctionType(FI);
+
   // Since this is the first time we've created this IFunc, make sure
   // that we put this multiversioned function into the list to be
   // replaced later if necessary (target multiversioning only).
@@ -3770,7 +3761,7 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
 if (FD->isMultiVersion()) {
   UpdateMultiVersionNames(GD, FD, MangledName);
   if (!IsForDefinition)
-return GetOrCreateMultiVersionResolver(GD, Ty, FD);
+return GetOrCreateMultiVersionResolver(GD);
 }
   }
 

diff  

[clang] bed5ee3 - [clang] NFC: Enhance comments in CodeGen for multiversion function support.

2022-04-05 Thread Tom Honermann via cfe-commits

Author: Tom Honermann
Date: 2022-04-05T19:50:22-04:00
New Revision: bed5ee3f4ba2406658760ec4029ed222c6213ff7

URL: 
https://github.com/llvm/llvm-project/commit/bed5ee3f4ba2406658760ec4029ed222c6213ff7
DIFF: 
https://github.com/llvm/llvm-project/commit/bed5ee3f4ba2406658760ec4029ed222c6213ff7.diff

LOG: [clang] NFC: Enhance comments in CodeGen for multiversion function support.

Reviewed By: erichkeane

Differential Revision: https://reviews.llvm.org/D122955

Added: 


Modified: 
clang/include/clang/Basic/Attr.td
clang/lib/CodeGen/CodeGenModule.cpp
clang/lib/CodeGen/CodeGenModule.h

Removed: 




diff  --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 4789493399ec2..c7141ff463b38 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -2723,8 +2723,12 @@ def TargetClones : InheritableAttr {
 StringRef getFeatureStr(unsigned Index) const {
   return *(featuresStrs_begin() + Index);
 }
-// 'default' is always moved to the end, so it isn't considered
-// when mangling the index.
+// Given an index into the 'featuresStrs' sequence, compute a unique
+// ID to be used with function name mangling for the associated variant.
+// This mapping is necessary due to a requirement that the mangling ID
+// used for the "default" variant be the largest mangling ID in the
+// variant set. Duplicate variants present in 'featuresStrs' are also
+// assigned their own unique ID (the mapping is bijective).
 unsigned getMangledIndex(unsigned Index) const {
   if (getFeatureStr(Index) == "default")
 return std::count_if(featuresStrs_begin(), featuresStrs_end(),
@@ -2734,9 +2738,10 @@ def TargetClones : InheritableAttr {
[](StringRef S) { return S != "default"; });
 }
 
-// True if this is the first of this version to appear in the config 
string.
-// This is used to make sure we don't try to emit this function multiple
-// times.
+// Given an index into the 'featuresStrs' sequence, determine if the
+// index corresponds to the first instance of the named variant. This
+// is used to skip over duplicate variant instances when iterating over
+// 'featuresStrs'.
 bool isFirstOfVersion(unsigned Index) const {
   StringRef FeatureStr(getFeatureStr(Index));
   return 0 == std::count_if(

diff  --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index 5536626d0691a..72fea25a28cfb 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -3768,7 +3768,7 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
 }
 
 if (FD->isMultiVersion()) {
-UpdateMultiVersionNames(GD, FD, MangledName);
+  UpdateMultiVersionNames(GD, FD, MangledName);
   if (!IsForDefinition)
 return GetOrCreateMultiVersionResolver(GD, Ty, FD);
 }

diff  --git a/clang/lib/CodeGen/CodeGenModule.h 
b/clang/lib/CodeGen/CodeGenModule.h
index a95949109c371..a68c681a2dd1b 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -348,8 +348,9 @@ class CodeGenModule : public CodeGenTypeCache {
   /// is defined once we get to the end of the of the translation unit.
   std::vector Aliases;
 
-  /// List of multiversion functions that have to be emitted.  Used to make 
sure
-  /// we properly emit the iFunc.
+  /// List of multiversion functions to be emitted. This list is processed in
+  /// conjunction with other deferred symbols and is used to ensure that
+  /// multiversion function resolvers and ifuncs are defined and emitted.
   std::vector MultiVersionFuncs;
 
   typedef llvm::StringMap > ReplacementsTy;
@@ -1466,9 +1467,20 @@ class CodeGenModule : public CodeGenTypeCache {
   llvm::AttributeList ExtraAttrs = llvm::AttributeList(),
   ForDefinition_t IsForDefinition = NotForDefinition);
 
+  // References to multiversion functions are resolved through an implicitly
+  // defined resolver function. This function is responsible for creating
+  // the resolver symbol for the provided declaration. The value returned
+  // will be for an ifunc (llvm::GlobalIFunc) if the current target supports
+  // that feature and for a regular function (llvm::GlobalValue) otherwise.
   llvm::Constant *GetOrCreateMultiVersionResolver(GlobalDecl GD,
   llvm::Type *DeclTy,
   const FunctionDecl *FD);
+
+  // In scenarios where a function is not known to be a multiversion function
+  // until a later declaration, it is sometimes necessary to change the
+  // previously created mangled name to align with requirements of whatever
+  // multiversion function kind the function is now known to be. This function
+  // is responsible for performing such mangled name 

[clang] 7c53fc4 - [clang] Emit target_clones resolver functions as COMDAT.

2022-04-05 Thread Tom Honermann via cfe-commits

Author: Tom Honermann
Date: 2022-04-05T15:34:35-04:00
New Revision: 7c53fc4fe1308f5b2a7527d14ea41fabb18109b8

URL: 
https://github.com/llvm/llvm-project/commit/7c53fc4fe1308f5b2a7527d14ea41fabb18109b8
DIFF: 
https://github.com/llvm/llvm-project/commit/7c53fc4fe1308f5b2a7527d14ea41fabb18109b8.diff

LOG: [clang] Emit target_clones resolver functions as COMDAT.

Previously, resolver functions synthesized for target_clones multiversion
functions were not emitted as COMDAT. Now fixed.

Added: 


Modified: 
clang/lib/CodeGen/CodeGenModule.cpp
clang/test/CodeGen/attr-target-clones.c

Removed: 




diff  --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index 4d24c33f51d02..ddcf564e688fe 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -3454,6 +3454,10 @@ void CodeGenModule::EmitTargetClonesResolver(GlobalDecl 
GD) {
 Options.emplace_back(cast(Func), Architecture, Feature);
   }
 
+  if (supportsCOMDAT())
+ResolverFunc->setComdat(
+getModule().getOrInsertComdat(ResolverFunc->getName()));
+
   const TargetInfo  = getTarget();
   std::stable_sort(
   Options.begin(), Options.end(),

diff  --git a/clang/test/CodeGen/attr-target-clones.c 
b/clang/test/CodeGen/attr-target-clones.c
index 2ba3fb0158044..ecb36a41bab88 100644
--- a/clang/test/CodeGen/attr-target-clones.c
+++ b/clang/test/CodeGen/attr-target-clones.c
@@ -1,6 +1,18 @@
 // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s 
--check-prefixes=LINUX,CHECK
 // RUN: %clang_cc1 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s 
--check-prefixes=WINDOWS,CHECK
 
+// LINUX: $foo.resolver = comdat any
+// LINUX: $foo_dupes.resolver = comdat any
+// LINUX: $unused.resolver = comdat any
+// LINUX: $foo_inline.resolver = comdat any
+// LINUX: $foo_inline2.resolver = comdat any
+
+// WINDOWS: $foo = comdat any
+// WINDOWS: $foo_dupes = comdat any
+// WINDOWS: $unused = comdat any
+// WINDOWS: $foo_inline = comdat any
+// WINDOWS: $foo_inline2 = comdat any
+
 // LINUX: @foo.ifunc = weak_odr ifunc i32 (), i32 ()* ()* @foo.resolver
 // LINUX: @foo_dupes.ifunc = weak_odr ifunc void (), void ()* ()* 
@foo_dupes.resolver
 // LINUX: @unused.ifunc = weak_odr ifunc void (), void ()* ()* @unused.resolver
@@ -10,26 +22,26 @@
 int __attribute__((target_clones("sse4.2, default"))) foo(void) { return 0; }
 // LINUX: define {{.*}}i32 @foo.sse4.2.0()
 // LINUX: define {{.*}}i32 @foo.default.1()
-// LINUX: define i32 ()* @foo.resolver()
+// LINUX: define i32 ()* @foo.resolver() comdat
 // LINUX: ret i32 ()* @foo.sse4.2.0
 // LINUX: ret i32 ()* @foo.default.1
 
 // WINDOWS: define dso_local i32 @foo.sse4.2.0()
 // WINDOWS: define dso_local i32 @foo.default.1()
-// WINDOWS: define dso_local i32 @foo()
+// WINDOWS: define dso_local i32 @foo() comdat
 // WINDOWS: musttail call i32 @foo.sse4.2.0
 // WINDOWS: musttail call i32 @foo.default.1
 
 __attribute__((target_clones("default,default ,sse4.2"))) void foo_dupes(void) 
{}
 // LINUX: define {{.*}}void @foo_dupes.default.1()
 // LINUX: define {{.*}}void @foo_dupes.sse4.2.0()
-// LINUX: define void ()* @foo_dupes.resolver()
+// LINUX: define void ()* @foo_dupes.resolver() comdat
 // LINUX: ret void ()* @foo_dupes.sse4.2.0
 // LINUX: ret void ()* @foo_dupes.default.1
 
 // WINDOWS: define dso_local void @foo_dupes.default.1()
 // WINDOWS: define dso_local void @foo_dupes.sse4.2.0()
-// WINDOWS: define dso_local void @foo_dupes()
+// WINDOWS: define dso_local void @foo_dupes() comdat
 // WINDOWS: musttail call void @foo_dupes.sse4.2.0
 // WINDOWS: musttail call void @foo_dupes.default.1
 
@@ -52,13 +64,13 @@ int bar(void) {
 void __attribute__((target_clones("default, arch=ivybridge"))) unused(void) {}
 // LINUX: define {{.*}}void @unused.default.1()
 // LINUX: define {{.*}}void @unused.arch_ivybridge.0()
-// LINUX: define void ()* @unused.resolver()
+// LINUX: define void ()* @unused.resolver() comdat
 // LINUX: ret void ()* @unused.arch_ivybridge.0
 // LINUX: ret void ()* @unused.default.1
 
 // WINDOWS: define dso_local void @unused.default.1()
 // WINDOWS: define dso_local void @unused.arch_ivybridge.0()
-// WINDOWS: define dso_local void @unused()
+// WINDOWS: define dso_local void @unused() comdat
 // WINDOWS: musttail call void @unused.arch_ivybridge.0
 // WINDOWS: musttail call void @unused.default.1
 
@@ -79,12 +91,12 @@ int bar3(void) {
 }
 
 // Deferred emission of foo_inline, which got delayed because it is inline.
-// LINUX: define i32 ()* @foo_inline.resolver()
+// LINUX: define i32 ()* @foo_inline.resolver() comdat
 // LINUX: ret i32 ()* @foo_inline.arch_sandybridge.0
 // LINUX: ret i32 ()* @foo_inline.sse4.2.1
 // LINUX: ret i32 ()* @foo_inline.default.2
 
-// WINDOWS: define dso_local i32 @foo_inline()
+// WINDOWS: define dso_local i32 @foo_inline() comdat
 // WINDOWS: musttail call i32 

[clang] 3531a4f - [clang] NFC: Extend comdat validation in target multiversion function tests.

2022-04-05 Thread Tom Honermann via cfe-commits

Author: Tom Honermann
Date: 2022-04-05T15:34:35-04:00
New Revision: 3531a4fa3b7038d43ac20f56871da88aa25bf53d

URL: 
https://github.com/llvm/llvm-project/commit/3531a4fa3b7038d43ac20f56871da88aa25bf53d
DIFF: 
https://github.com/llvm/llvm-project/commit/3531a4fa3b7038d43ac20f56871da88aa25bf53d.diff

LOG: [clang] NFC: Extend comdat validation in target multiversion function 
tests.

Added: 


Modified: 
clang/test/CodeGen/attr-target-mv.c

Removed: 




diff  --git a/clang/test/CodeGen/attr-target-mv.c 
b/clang/test/CodeGen/attr-target-mv.c
index 39661ee36416e..12033bde9b137 100644
--- a/clang/test/CodeGen/attr-target-mv.c
+++ b/clang/test/CodeGen/attr-target-mv.c
@@ -76,9 +76,45 @@ inline __attribute__((target("default"))) void 
pr50025b(void) { must_be_emitted(
 inline __attribute__((target("default"))) void pr50025c(void) { pr50025b(); }
 void calls_pr50025c(void) { pr50025c(); }
 
+// LINUX: $foo.resolver = comdat any
+// LINUX: $foo_inline.resolver = comdat any
+// LINUX: $foo_decls.resolver = comdat any
+// LINUX: $foo_multi.resolver = comdat any
+// LINUX: $fwd_decl_default.resolver = comdat any
+// LINUX: $fwd_decl_avx.resolver = comdat any
+// LINUX: $pr50025.resolver = comdat any
+// LINUX: $pr50025c.resolver = comdat any
+// LINUX: $pr50025b.resolver = comdat any
+
+// WINDOWS: $foo.resolver = comdat any
+// WINDOWS: $foo_inline.resolver = comdat any
+// WINDOWS: $foo_decls.resolver = comdat any
+// WINDOWS: $foo_multi.resolver = comdat any
+// WINDOWS: $fwd_decl_default.resolver = comdat any
+// WINDOWS: $fwd_decl_avx.resolver = comdat any
+// WINDOWS: $foo_used = comdat any
+// WINDOWS: $foo_used2.avx_sse4.2 = comdat any
+// WINDOWS: $pr50025.resolver = comdat any
+// WINDOWS: $pr50025c.resolver = comdat any
+// WINDOWS: $foo_inline.sse4.2 = comdat any
+// WINDOWS: $foo_inline.arch_ivybridge = comdat any
+// WINDOWS: $foo_inline = comdat any
+// WINDOWS: $foo_decls = comdat any
+// WINDOWS: $foo_decls.sse4.2 = comdat any
+// WINDOWS: $foo_multi = comdat any
+// WINDOWS: $foo_multi.avx_sse4.2 = comdat any
+// WINDOWS: $foo_multi.fma4_sse4.2 = comdat any
+// WINDOWS: $foo_multi.arch_ivybridge_fma4_sse4.2 = comdat any
+// WINDOWS: $pr50025 = comdat any
+// WINDOWS: $pr50025c = comdat any
+// WINDOWS: $pr50025b.resolver = comdat any
+// WINDOWS: $pr50025b = comdat any
+
+
 // LINUX: @llvm.compiler.used = appending global [2 x i8*] [i8* bitcast (void 
(i32, double)* @foo_used to i8*), i8* bitcast (void (i32, double)* 
@foo_used2.avx_sse4.2 to i8*)], section "llvm.metadata"
 // WINDOWS: @llvm.used = appending global [2 x i8*] [i8* bitcast (void (i32, 
double)* @foo_used to i8*), i8* bitcast (void (i32, double)* 
@foo_used2.avx_sse4.2 to i8*)], section "llvm.metadata"
 
+
 // LINUX: @foo.ifunc = weak_odr ifunc i32 (), i32 ()* ()* @foo.resolver
 // LINUX: @foo_inline.ifunc = weak_odr ifunc i32 (), i32 ()* ()* 
@foo_inline.resolver
 // LINUX: @foo_decls.ifunc = weak_odr ifunc void (), void ()* ()* 
@foo_decls.resolver
@@ -325,11 +361,20 @@ void calls_pr50025c(void) { pr50025c(); }
 // LINUX: define linkonce void @pr50025()
 // LINUX: call void @must_be_emitted
 // LINUX: define internal void @must_be_emitted()
-// WINDOWS: define linkonce_odr dso_local void @pr50025()
+// WINDOWS: define linkonce_odr dso_local void @pr50025() #{{[0-9]*}} comdat
 // WINDOWS: call void @must_be_emitted
 // WINDOWS: define internal void @must_be_emitted()
 
 // LINUX: define linkonce void @pr50025c()
+// LINUX: call void @pr50025b.ifunc()
+// WINDOWS: define linkonce_odr dso_local void @pr50025c() #{{[0-9]*}} comdat
+// WINDOWS: call void @pr50025b.resolver()
+
+// LINUX: define weak_odr void ()* @pr50025b.resolver() comdat
+// LINUX: ret void ()* @pr50025b
 // LINUX: define linkonce void @pr50025b()
-// WINDOWS: define linkonce_odr dso_local void @pr50025c()
-// WINDOWS: define linkonce_odr dso_local void @pr50025b()
+// LINUX: call void @must_be_emitted()
+// WINDOWS: define weak_odr dso_local void @pr50025b.resolver() comdat
+// WINDOWS: musttail call void @pr50025b()
+// WINDOWS: define linkonce_odr dso_local void @pr50025b() #{{[0-9]*}} comdat
+// WINDOWS: call void @must_be_emitted()



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


[clang] 059a953 - [clang] [OpenMP] Diagnose use of 'target_clones' in OpenMP variant declarations.

2022-03-21 Thread Tom Honermann via cfe-commits

Author: Tom Honermann
Date: 2022-03-21T13:39:44-04:00
New Revision: 059a953d8819b361b33205c109b5e903801613a2

URL: 
https://github.com/llvm/llvm-project/commit/059a953d8819b361b33205c109b5e903801613a2
DIFF: 
https://github.com/llvm/llvm-project/commit/059a953d8819b361b33205c109b5e903801613a2.diff

LOG: [clang] [OpenMP] Diagnose use of 'target_clones' in OpenMP variant 
declarations.

Previously, OpenMP variant declarations for a function declaration that included
the 'cpu_dispatch', 'cpu_specific', or 'target' attributes was diagnosed, but
one with the 'target_clones' attribute was not. Now fixed.

Reviewed By: erichkeane, jdoerfert

Differential Revision: https://reviews.llvm.org/D121963

Added: 


Modified: 
clang/lib/Sema/SemaOpenMP.cpp
clang/test/OpenMP/declare_variant_messages.c

Removed: 




diff  --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index cfd8b60d9f03c..4a74d4f43bf84 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -7036,11 +7036,11 @@ 
Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG,
   }
 
   auto & = [](const FunctionDecl *FD) {
-return FD->hasAttrs() &&
-   (FD->hasAttr() || FD->hasAttr() ||
-FD->hasAttr());
+// The 'target' attribute needs to be separately checked because it does
+// not always signify a multiversion function declaration.
+return FD->isMultiVersion() || FD->hasAttr();
   };
-  // OpenMP is not compatible with CPU-specific attributes.
+  // OpenMP is not compatible with multiversion function attributes.
   if (HasMultiVersionAttributes(FD)) {
 Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
 << SR;

diff  --git a/clang/test/OpenMP/declare_variant_messages.c 
b/clang/test/OpenMP/declare_variant_messages.c
index e00d1615ef61a..6969188d214d2 100644
--- a/clang/test/OpenMP/declare_variant_messages.c
+++ b/clang/test/OpenMP/declare_variant_messages.c
@@ -162,9 +162,8 @@ __attribute__((target("sse"))) void 
incompat_attr_target(void); // expected-erro
 #pragma omp declare variant(incompat_attr_variant) 
match(implementation={vendor(llvm)})
 __attribute__((target("default"))) void incompat_attr_target_default(void); // 
expected-error {{'#pragma omp declare variant' is not compatible with any 
target-specific attributes}}
 
-// FIXME: No diagnostics are produced for use of the 'target_clones' attribute 
in an OMP variant declaration.
 #pragma omp declare variant(incompat_attr_variant) 
match(implementation={vendor(llvm)})
-__attribute__((target_clones("sse,default"))) void 
incompat_attr_target_clones(void);
+__attribute__((target_clones("sse,default"))) void 
incompat_attr_target_clones(void); // expected-error {{'#pragma omp declare 
variant' is not compatible with any target-specific attributes}}
 
 void marked(void);
 void not_marked(void);



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


[clang] 8ff8c3a - [clang] [OpenMP] Extend OpenMP variant declaration tests.

2022-03-21 Thread Tom Honermann via cfe-commits

Author: Tom Honermann
Date: 2022-03-21T13:39:44-04:00
New Revision: 8ff8c3ac0dd675319d779a1aa0087e8a0d5a81b2

URL: 
https://github.com/llvm/llvm-project/commit/8ff8c3ac0dd675319d779a1aa0087e8a0d5a81b2
DIFF: 
https://github.com/llvm/llvm-project/commit/8ff8c3ac0dd675319d779a1aa0087e8a0d5a81b2.diff

LOG: [clang] [OpenMP] Extend OpenMP variant declaration tests.

This change extends the existing diagnostic tests for OpenMP variant
declarations to cover diagnostics for declarations that include
multiversion function attributes. The new tests demonstrate a missing
check for the 'target_clones' attribute.

Reviewed By: erichkeane, jdoerfert

Differential Revision: https://reviews.llvm.org/D121962

Added: 


Modified: 
clang/test/OpenMP/declare_variant_messages.c

Removed: 




diff  --git a/clang/test/OpenMP/declare_variant_messages.c 
b/clang/test/OpenMP/declare_variant_messages.c
index 5618e1bbe1d3d..e00d1615ef61a 100644
--- a/clang/test/OpenMP/declare_variant_messages.c
+++ b/clang/test/OpenMP/declare_variant_messages.c
@@ -142,6 +142,30 @@ int 
diff _ret_variant(void);
 #pragma omp declare variant(
diff _ret_variant) match(xxx={}) // expected-error {{variant in '#pragma omp 
declare variant' with type 'int (void)' is incompatible with type 'void 
(void)'}} expected-warning {{'xxx' is not a valid context set in a `declare 
variant`; set ignored}} expected-note {{context set options are: 'construct' 
'device' 'implementation' 'user'}} expected-note {{the ignored set spans until 
here}}
 void 
diff _ret(void);
 
+void incompat_attr_variant(void);
+
+#pragma omp declare variant(incompat_attr_variant) 
match(implementation={vendor(llvm)})
+__attribute__((cpu_dispatch(generic))) void incompat_attr_cpu_dispatch(void); 
// expected-error {{'#pragma omp declare variant' is not compatible with any 
target-specific attributes}}
+
+#pragma omp declare variant(incompat_attr_variant) 
match(implementation={vendor(llvm)})
+__attribute__((cpu_specific(generic))) void incompat_attr_cpu_specific(void); 
// expected-error {{'#pragma omp declare variant' is not compatible with any 
target-specific attributes}}
+
+// 'incompat_attr_target' is not a multiversion function until...
+#pragma omp declare variant(incompat_attr_variant) 
match(implementation={vendor(llvm)})
+__attribute__((target("mmx"))) void incompat_attr_target(void); // 
expected-error {{'#pragma omp declare variant' is not compatible with any 
target-specific attributes}}
+
+// This declaration makes it one.
+#pragma omp declare variant(incompat_attr_variant) 
match(implementation={vendor(llvm)})
+__attribute__((target("sse"))) void incompat_attr_target(void); // 
expected-error {{'#pragma omp declare variant' is not compatible with any 
target-specific attributes}}
+
+// 'incompat_attr_target_default' is always a multiversion function.
+#pragma omp declare variant(incompat_attr_variant) 
match(implementation={vendor(llvm)})
+__attribute__((target("default"))) void incompat_attr_target_default(void); // 
expected-error {{'#pragma omp declare variant' is not compatible with any 
target-specific attributes}}
+
+// FIXME: No diagnostics are produced for use of the 'target_clones' attribute 
in an OMP variant declaration.
+#pragma omp declare variant(incompat_attr_variant) 
match(implementation={vendor(llvm)})
+__attribute__((target_clones("sse,default"))) void 
incompat_attr_target_clones(void);
+
 void marked(void);
 void not_marked(void);
 



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


[clang] 0cceee7 - [clang] Produce a "multiversion" annotation in textual AST output.

2022-03-21 Thread Tom Honermann via cfe-commits

Author: Tom Honermann
Date: 2022-03-21T13:39:44-04:00
New Revision: 0cceee755992820362d5df5698da8bce762b9fe3

URL: 
https://github.com/llvm/llvm-project/commit/0cceee755992820362d5df5698da8bce762b9fe3
DIFF: 
https://github.com/llvm/llvm-project/commit/0cceee755992820362d5df5698da8bce762b9fe3.diff

LOG: [clang] Produce a "multiversion" annotation in textual AST output.

This change adds a "multiversion" annotation to textual AST output.
For example:
  FunctionDecl 0xb6628b0  col:5 multiversion foo 'int (void)'

Reviewed By: aaron.ballman

Differential Revision: https://reviews.llvm.org/D121961

Added: 
clang/test/AST/ast-dump-funcs-multiversion.c

Modified: 
clang/lib/AST/TextNodeDumper.cpp

Removed: 




diff  --git a/clang/lib/AST/TextNodeDumper.cpp 
b/clang/lib/AST/TextNodeDumper.cpp
index 67c934847c7f9..ba8b7b692d588 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -283,6 +283,8 @@ void TextNodeDumper::Visit(const Decl *D) {
   OS << " constexpr";
 if (FD->isConsteval())
   OS << " consteval";
+if (FD->isMultiVersion())
+  OS << " multiversion";
   }
 
   if (!isa(*D)) {

diff  --git a/clang/test/AST/ast-dump-funcs-multiversion.c 
b/clang/test/AST/ast-dump-funcs-multiversion.c
new file mode 100644
index 0..5db06795ea598
--- /dev/null
+++ b/clang/test/AST/ast-dump-funcs-multiversion.c
@@ -0,0 +1,23 @@
+// Test without serialization:
+// RUN: %clang_cc1 -triple x86_64-pc-linux -ast-dump -ast-dump-filter Test %s \
+// RUN: | FileCheck --strict-whitespace %s
+//
+// Test with serialization:
+// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-pch -o %t %s
+// RUN: %clang_cc1 -x c -triple x86_64-pc-linux -include-pch %t \
+// RUN:-ast-dump-all -ast-dump-filter Test /dev/null \
+// RUN: | sed -e "s/ //" -e "s/ imported//" \
+// RUN: | FileCheck --strict-whitespace %s
+
+void TestUnattributedMVF(void);
+// CHECK:  FunctionDecl 0x{{[^ ]*}} <{{.*}}> col:{{[0-9]*}} multiversion 
TestUnattributedMVF
+__attribute__((target("default"))) void TestUnattributedMVF(void);
+// CHECK:  FunctionDecl 0x{{[^ ]*}} prev 0x{{[^ ]*}} <{{.*}}> 
col:{{[0-9]*}} multiversion TestUnattributedMVF
+
+__attribute__((target("mmx"))) void TestNonMVF(void);
+// CHECK:  FunctionDecl 0x{{[^ ]*}} <{{.*}}> col:{{[0-9]*}} TestNonMVF
+
+__attribute__((target("mmx"))) void TestRetroMVF(void);
+// CHECK:  FunctionDecl 0x{{[^ ]*}} <{{.*}}> col:{{[0-9]*}} multiversion 
TestRetroMVF
+__attribute__((target("sse"))) void TestRetroMVF(void);
+// CHECK:  FunctionDecl 0x{{[^ ]*}} <{{.*}}> col:{{[0-9]*}} multiversion 
TestRetroMVF



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


[clang] 58c202a - [clang] NFC: Rename 'MVType' variables to 'MVKind' for consistency with their type.

2022-03-21 Thread Tom Honermann via cfe-commits

Author: Tom Honermann
Date: 2022-03-21T13:39:43-04:00
New Revision: 58c202a3d83dab0c4abeb19c3eeff27d83f6c2b5

URL: 
https://github.com/llvm/llvm-project/commit/58c202a3d83dab0c4abeb19c3eeff27d83f6c2b5
DIFF: 
https://github.com/llvm/llvm-project/commit/58c202a3d83dab0c4abeb19c3eeff27d83f6c2b5.diff

LOG: [clang] NFC: Rename 'MVType' variables to 'MVKind' for consistency with 
their type.

Reviewed By: aaron.ballman

Differential Revision: https://reviews.llvm.org/D121960

Added: 


Modified: 
clang/lib/Sema/SemaDecl.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 385569b186393..ad05e9affc7d0 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -10361,14 +10361,14 @@ static bool CheckMultiVersionValue(Sema , const 
FunctionDecl *FD) {
 // Provide a white-list of attributes that are allowed to be combined with
 // multiversion functions.
 static bool AttrCompatibleWithMultiVersion(attr::Kind Kind,
-   MultiVersionKind MVType) {
+   MultiVersionKind MVKind) {
   // Note: this list/diagnosis must match the list in
   // checkMultiversionAttributesAllSame.
   switch (Kind) {
   default:
 return false;
   case attr::Used:
-return MVType == MultiVersionKind::Target;
+return MVKind == MultiVersionKind::Target;
   case attr::NonNull:
   case attr::NoThrow:
 return true;
@@ -10378,10 +10378,10 @@ static bool AttrCompatibleWithMultiVersion(attr::Kind 
Kind,
 static bool checkNonMultiVersionCompatAttributes(Sema ,
  const FunctionDecl *FD,
  const FunctionDecl *CausedFD,
- MultiVersionKind MVType) {
-  const auto Diagnose = [FD, CausedFD, MVType](Sema , const Attr *A) {
+ MultiVersionKind MVKind) {
+  const auto Diagnose = [FD, CausedFD, MVKind](Sema , const Attr *A) {
 S.Diag(FD->getLocation(), diag::err_multiversion_disallowed_other_attr)
-<< static_cast(MVType) << A;
+<< static_cast(MVKind) << A;
 if (CausedFD)
   S.Diag(CausedFD->getLocation(), diag::note_multiversioning_caused_here);
 return true;
@@ -10391,20 +10391,20 @@ static bool checkNonMultiVersionCompatAttributes(Sema 
,
 switch (A->getKind()) {
 case attr::CPUDispatch:
 case attr::CPUSpecific:
-  if (MVType != MultiVersionKind::CPUDispatch &&
-  MVType != MultiVersionKind::CPUSpecific)
+  if (MVKind != MultiVersionKind::CPUDispatch &&
+  MVKind != MultiVersionKind::CPUSpecific)
 return Diagnose(S, A);
   break;
 case attr::Target:
-  if (MVType != MultiVersionKind::Target)
+  if (MVKind != MultiVersionKind::Target)
 return Diagnose(S, A);
   break;
 case attr::TargetClones:
-  if (MVType != MultiVersionKind::TargetClones)
+  if (MVKind != MultiVersionKind::TargetClones)
 return Diagnose(S, A);
   break;
 default:
-  if (!AttrCompatibleWithMultiVersion(A->getKind(), MVType))
+  if (!AttrCompatibleWithMultiVersion(A->getKind(), MVKind))
 return Diagnose(S, A);
   break;
 }
@@ -10528,7 +10528,7 @@ bool Sema::areMultiversionVariantFunctionsCompatible(
 static bool CheckMultiVersionAdditionalRules(Sema , const FunctionDecl 
*OldFD,
  const FunctionDecl *NewFD,
  bool CausesMV,
- MultiVersionKind MVType) {
+ MultiVersionKind MVKind) {
   if (!S.getASTContext().getTargetInfo().supportsMultiVersioning()) {
 S.Diag(NewFD->getLocation(), diag::err_multiversion_not_supported);
 if (OldFD)
@@ -10536,15 +10536,15 @@ static bool CheckMultiVersionAdditionalRules(Sema , 
const FunctionDecl *OldFD,
 return true;
   }
 
-  bool IsCPUSpecificCPUDispatchMVType =
-  MVType == MultiVersionKind::CPUDispatch ||
-  MVType == MultiVersionKind::CPUSpecific;
+  bool IsCPUSpecificCPUDispatchMVKind =
+  MVKind == MultiVersionKind::CPUDispatch ||
+  MVKind == MultiVersionKind::CPUSpecific;
 
   if (CausesMV && OldFD &&
-  checkNonMultiVersionCompatAttributes(S, OldFD, NewFD, MVType))
+  checkNonMultiVersionCompatAttributes(S, OldFD, NewFD, MVKind))
 return true;
 
-  if (checkNonMultiVersionCompatAttributes(S, NewFD, nullptr, MVType))
+  if (checkNonMultiVersionCompatAttributes(S, NewFD, nullptr, MVKind))
 return true;
 
   // Only allow transition to MultiVersion if it hasn't been used.
@@ -10557,11 +10557,11 @@ static bool CheckMultiVersionAdditionalRules(Sema , 
const FunctionDecl *OldFD,
   S.PDiag(diag::note_multiversioning_caused_here)),

[clang] 8b6f1cb - [clang] Add missing diagnostics for invalid overloads of multiversion functions in C.

2022-03-21 Thread Tom Honermann via cfe-commits

Author: Tom Honermann
Date: 2022-03-21T13:39:43-04:00
New Revision: 8b6f1cbb21c58e255156aa32ac55530c807055a9

URL: 
https://github.com/llvm/llvm-project/commit/8b6f1cbb21c58e255156aa32ac55530c807055a9
DIFF: 
https://github.com/llvm/llvm-project/commit/8b6f1cbb21c58e255156aa32ac55530c807055a9.diff

LOG: [clang] Add missing diagnostics for invalid overloads of multiversion 
functions in C.

Previously, an attempt to declare an overload of a multiversion function
in C was not properly diagnosed. In some cases, diagnostics were simply
missing. In other cases the following assertion failure occured...
```
Assertion `(Previous.empty() || llvm::any_of(Previous, [](const NamedDecl *ND) 
{ return ND->hasAttr(); })) && "Non-redecls shouldn't happen without 
overloadable present"' failed.
```
... or the following diagnostic was spuriously issued.
```
error: at most one overload for a given name may lack the 'overloadable' 
attribute
```

The diagnostics issued in some cases could be improved. When the function
type of a redeclaration does not match the prior declaration, it would be
preferable to diagnose the type mismatch before diagnosing mismatched
attributes. Diagnostics are also missing for some cases.

Reviewed By: erichkeane

Differential Revision: https://reviews.llvm.org/D121959

Added: 


Modified: 
clang/lib/Sema/SemaDecl.cpp
clang/test/Sema/attr-cpuspecific.c
clang/test/Sema/attr-target-clones.c
clang/test/Sema/attr-target-mv.c

Removed: 




diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 68e3a7461deb1..385569b186393 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -1460,27 +1460,38 @@ void Sema::ActOnExitFunctionContext() {
   assert(CurContext && "Popped translation unit!");
 }
 
-/// Determine whether we allow overloading of the function
-/// PrevDecl with another declaration.
+/// Determine whether overloading is allowed for a new function
+/// declaration considering prior declarations of the same name.
 ///
 /// This routine determines whether overloading is possible, not
-/// whether some new function is actually an overload. It will return
-/// true in C++ (where we can always provide overloads) or, as an
-/// extension, in C when the previous function is already an
-/// overloaded function declaration or has the "overloadable"
-/// attribute.
-static bool AllowOverloadingOfFunction(LookupResult ,
+/// whether a new declaration actually overloads a previous one.
+/// It will return true in C++ (where overloads are alway permitted)
+/// or, as a C extension, when either the new declaration or a
+/// previous one is declared with the 'overloadable' attribute.
+static bool AllowOverloadingOfFunction(const LookupResult ,
ASTContext ,
const FunctionDecl *New) {
-  if (Context.getLangOpts().CPlusPlus)
+  if (Context.getLangOpts().CPlusPlus || New->hasAttr())
 return true;
 
-  if (Previous.getResultKind() == LookupResult::FoundOverloaded)
-return true;
+  // Multiversion function declarations are not overloads in the
+  // usual sense of that term, but lookup will report that an
+  // overload set was found if more than one multiversion function
+  // declaration is present for the same name. It is therefore
+  // inadequate to assume that some prior declaration(s) had
+  // the overloadable attribute; checking is required. Since one
+  // declaration is permitted to omit the attribute, it is necessary
+  // to check at least two; hence the 'any_of' check below. Note that
+  // the overloadable attribute is implicitly added to declarations
+  // that were required to have it but did not.
+  if (Previous.getResultKind() == LookupResult::FoundOverloaded) {
+return llvm::any_of(Previous, [](const NamedDecl *ND) {
+  return ND->hasAttr();
+});
+  } else if (Previous.getResultKind() == LookupResult::Found)
+return Previous.getFoundDecl()->hasAttr();
 
-  return Previous.getResultKind() == LookupResult::Found &&
- (Previous.getFoundDecl()->hasAttr() ||
-  New->hasAttr());
+  return false;
 }
 
 /// Add this decl to the scope shadowed decl chains.
@@ -10705,13 +10716,17 @@ static bool CheckMultiVersionAdditionalDecl(
   bool UseMemberUsingDeclRules =
   S.CurContext->isRecord() && !NewFD->getFriendObjectKind();
 
+  bool MayNeedOverloadableChecks =
+  AllowOverloadingOfFunction(Previous, S.Context, NewFD);
+
   // Next, check ALL non-overloads to see if this is a redeclaration of a
   // previous member of the MultiVersion set.
   for (NamedDecl *ND : Previous) {
 FunctionDecl *CurFD = ND->getAsFunction();
 if (!CurFD)
   continue;
-if (S.IsOverload(NewFD, CurFD, UseMemberUsingDeclRules))
+if (MayNeedOverloadableChecks &&
+S.IsOverload(NewFD, CurFD, UseMemberUsingDeclRules))
   continue;
 
 

[clang] 42e4c5b - [clang] NFC: Remove forced type merging in multiversion function checks.

2022-03-21 Thread Tom Honermann via cfe-commits

Author: Tom Honermann
Date: 2022-03-21T13:39:43-04:00
New Revision: 42e4c5b2610d0008d52f2ebf08961e8ae0adb58b

URL: 
https://github.com/llvm/llvm-project/commit/42e4c5b2610d0008d52f2ebf08961e8ae0adb58b
DIFF: 
https://github.com/llvm/llvm-project/commit/42e4c5b2610d0008d52f2ebf08961e8ae0adb58b.diff

LOG: [clang] NFC: Remove forced type merging in multiversion function checks.

Checking of multiversion function declarations performed by various functions
in clang/lib/Sema/SemaDecl.cpp previously forced the valus of a passed in
'MergeTypeWithPrevious' reference argument in several scenarios. This was
unnecessary and possibly incorrect in the one case that the value
was forced to 'true' (though seemingly unobservably so).

Reviewed By: erichkeane

Differential Revision: https://reviews.llvm.org/D121958

Added: 


Modified: 
clang/lib/Sema/SemaDecl.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 5bc01e80dad05..68e3a7461deb1 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -10596,8 +10596,7 @@ static bool 
PreviousDeclsHaveMultiVersionAttribute(const FunctionDecl *FD) {
 
 static bool CheckTargetCausesMultiVersioning(
 Sema , FunctionDecl *OldFD, FunctionDecl *NewFD, const TargetAttr *NewTA,
-bool , NamedDecl *, bool ,
-LookupResult ) {
+bool , NamedDecl *, LookupResult ) {
   const auto *OldTA = OldFD->getAttr();
   ParsedTargetAttr NewParsed = NewTA->parse();
   // Sort order doesn't matter, it just needs to be consistent.
@@ -10662,7 +10661,6 @@ static bool CheckTargetCausesMultiVersioning(
   OldFD->setIsMultiVersion();
   NewFD->setIsMultiVersion();
   Redeclaration = false;
-  MergeTypeWithPrevious = false;
   OldDecl = nullptr;
   Previous.clear();
   return false;
@@ -10687,7 +10685,7 @@ static bool CheckMultiVersionAdditionalDecl(
 MultiVersionKind NewMVType, const TargetAttr *NewTA,
 const CPUDispatchAttr *NewCPUDisp, const CPUSpecificAttr *NewCPUSpec,
 const TargetClonesAttr *NewClones, bool , NamedDecl 
*,
-bool , LookupResult ) {
+LookupResult ) {
 
   MultiVersionKind OldMVType = OldFD->getMultiVersionKind();
   // Disallow mixing of multiversioning types.
@@ -10743,7 +10741,6 @@ static bool CheckMultiVersionAdditionalDecl(
   const auto *CurClones = CurFD->getAttr();
   Redeclaration = true;
   OldDecl = CurFD;
-  MergeTypeWithPrevious = true;
   NewFD->setIsMultiVersion();
 
   if (CurClones && NewClones &&
@@ -10846,7 +10843,6 @@ static bool CheckMultiVersionAdditionalDecl(
 
   NewFD->setIsMultiVersion();
   Redeclaration = false;
-  MergeTypeWithPrevious = false;
   OldDecl = nullptr;
   Previous.clear();
   return false;
@@ -10860,7 +10856,6 @@ static bool CheckMultiVersionAdditionalDecl(
 /// Returns true if there was an error, false otherwise.
 static bool CheckMultiVersionFunction(Sema , FunctionDecl *NewFD,
   bool , NamedDecl *,
-  bool ,
   LookupResult ) {
   const auto *NewTA = NewFD->getAttr();
   const auto *NewCPUDisp = NewFD->getAttr();
@@ -10909,8 +10904,7 @@ static bool CheckMultiVersionFunction(Sema , 
FunctionDecl *NewFD,
 switch (MVType) {
 case MultiVersionKind::Target:
   return CheckTargetCausesMultiVersioning(S, OldFD, NewFD, NewTA,
-  Redeclaration, OldDecl,
-  MergeTypeWithPrevious, Previous);
+  Redeclaration, OldDecl, 
Previous);
 case MultiVersionKind::TargetClones:
   if (OldFD->isUsed(false)) {
 NewFD->setInvalidDecl();
@@ -10928,9 +10922,9 @@ static bool CheckMultiVersionFunction(Sema , 
FunctionDecl *NewFD,
   // At this point, we have a multiversion function decl (in OldFD) AND an
   // appropriate attribute in the current function decl.  Resolve that these 
are
   // still compatible with previous declarations.
-  return CheckMultiVersionAdditionalDecl(
-  S, OldFD, NewFD, MVType, NewTA, NewCPUDisp, NewCPUSpec, NewClones,
-  Redeclaration, OldDecl, MergeTypeWithPrevious, Previous);
+  return CheckMultiVersionAdditionalDecl(S, OldFD, NewFD, MVType, NewTA,
+ NewCPUDisp, NewCPUSpec, NewClones,
+ Redeclaration, OldDecl, Previous);
 }
 
 /// Perform semantic checking of a new function declaration.
@@ -11020,8 +11014,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, 
FunctionDecl *NewFD,
 }
   }
 
-  if (CheckMultiVersionFunction(*this, NewFD, Redeclaration, OldDecl,
-MergeTypeWithPrevious, Previous))
+  if (CheckMultiVersionFunction(*this, NewFD, Redeclaration, OldDecl, 
Previous))
 return Redeclaration;
 
   // PPC MMA non-pointer types are not 

  1   2   >