Original file line number Diff line number Diff line change
@@ -0,0 +1,310 @@
// RUN: %check_clang_tidy -std=c++98-or-later %s bugprone-tagged-union-member-count %t
// Test check with C++ features

typedef enum Tags3 {
tags3_1,
tags3_2,
tags3_3,
} Tags3;

typedef enum Tags4 {
tags4_1,
tags4_2,
tags4_3,
tags4_4,
} Tags4;

enum class Classtags3 {
classtags3_1,
classtags3_2,
classtags3_3,
};

enum class Typedtags3 : unsigned int {
typedtags3_1,
typedtags3_2,
typedtags3_3,
};

typedef union Union3 {
short *Shorts;
int *Ints;
float *Floats;
} Union3;

typedef union Union4 {
short *Shorts;
double *Doubles;
int *Ints;
float *Floats;
} Union4;

// It is not obvious which enum is the tag for the union.
class MaybeTaggedUnion1 { // No warnings expected.
enum Tags3 TagA;
enum Tags4 TagB;
union Union4 Data;
};

// It is not obvious which union does the tag belong to.
class MaybeTaggedUnion2 { // No warnings expected.
enum Tags3 Tag;
union Union3 DataB;
union Union3 DataA;
};

// It is not obvious which union does the tag belong to.
class MaybeTaggedUnion3 { // No warnings expected.
enum Tags3 Tag;
union {
int I1;
int I2;
int I3;
};
union {
float F1;
float F2;
float F3;
};
};

// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3)
class TaggedUnionClassPredefinedTagAndPredefinedUnion {
enum Tags3 Tag;
union Union4 Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3)
class TaggedUnionClassPredefinedTagAndInlineUnion {
enum Tags3 Tag;
union {
int *Ints;
char Characters[13];
class {
double Re;
double Im;
} Complex;
long L;
} Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3)
class TaggedUnionClassInlineTagAndPredefinedUnion {
enum {
tag1,
tag2,
tag3,
} Tag;
union Union4 Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3)
class TaggedUnionClassInlineTagAndInlineUnion {
enum {
tag1,
tag2,
tag3,
} Tag;
union {
int *Ints;
char Characters[13];
class {
double Re;
double Im;
} Complex;
long L;
} Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3)
class TaggedUnionClassWithNestedTaggedUnionClass {
enum Tags3 Tag;
union {
float F;
int I;
long L;
// CHECK-MESSAGES: :[[@LINE+1]]:11: warning: tagged union has more data members (4) than tags (3)
class Innerdecl {
enum Tags3 Tag;
union Union4 Data;
} Inner;
} Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3)
class TaggedUnionClassWithTypedefedTag {
Tags3 Tag;
Union4 Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:8: warning: tagged union has more data members (4) than tags (3)
struct TaggedUnionStructWithEnumClass {
enum Classtags3 Tag;
Union4 Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3)
class TaggedUnionClasswithEnumClass {
enum Classtags3 Tag;
Union4 Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:8: warning: tagged union has more data members (4) than tags (3)
struct TaggedUnionStructWithTypedEnum {
Typedtags3 Tag;
Union4 Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3)
class TaggedUnionClassWithTypedEnum {
Typedtags3 Tag;
Union4 Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:8: warning: tagged union has more data members (4) than tags (3)
struct AnonymousTaggedUnionStruct {
Tags3 Tag;
union {
char A;
short B;
int C;
long D;
};
};

// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3)
class TaggedUnionClassWithAnonymousUnion {
Tags3 Tag;
union {
char A;
short B;
int C;
long D;
};
};

namespace testnamespace {

enum Tags3 {
tags3_1,
tags3_2,
tags3_3,
};

union Union4 {
short *Shorts;
double *Doubles;
int *Ints;
float *Floats;
};

// CHECK-MESSAGES: :[[@LINE+1]]:8: warning: tagged union has more data members (4) than tags (3)
struct TaggedUnionStructInNamespace {
Tags3 Tags;
Union4 Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3)
class TaggedUnionClassInNamespace {
Tags3 Tags;
Union4 Data;
};

} // namespace testnamespace

// CHECK-MESSAGES: :[[@LINE+1]]:8: warning: tagged union has more data members (4) than tags (3)
struct TaggedUnionStructWithNamespacedTagAndUnion {
testnamespace::Tags3 Tags;
testnamespace::Union4 Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3)
class TaggedUnionClassWithNamespacedTagAndUnion {
testnamespace::Tags3 Tags;
testnamespace::Union4 Data;
};

// CHECK-MESSAGES: :[[@LINE+2]]:8: warning: tagged union has more data members (4) than tags (3)
template <typename Tag, typename Union>
struct TemplatedStructWithNamespacedTagAndUnion {
Tag Kind;
Union Data;
};

TemplatedStructWithNamespacedTagAndUnion<testnamespace::Union4, testnamespace::Tags3> TemplatedStruct3;

// CHECK-MESSAGES: :[[@LINE+2]]:7: warning: tagged union has more data members (4) than tags (3)
template <typename Tag, typename Union>
class TemplatedClassWithNamespacedTagAndUnion {
Tag Kind;
Union Data;
};

TemplatedClassWithNamespacedTagAndUnion<testnamespace::Union4, testnamespace::Tags3> TemplatedClass3;

// CHECK-MESSAGES: :[[@LINE+2]]:8: warning: tagged union has more data members (4) than tags (3)
template <typename Tag, typename Union>
struct TemplatedStruct {
Tag Kind;
Union Data;
};

TemplatedStruct<Tags3, Union3> TemplatedStruct1; // No warning expected
TemplatedStruct<Tags3, Union4> TemplatedStruct2;

// CHECK-MESSAGES: :[[@LINE+2]]:7: warning: tagged union has more data members (4) than tags (3)
template <typename Tag, typename Union>
class TemplatedClass {
Tag Kind;
Union Data;
};

TemplatedClass<Tags3, Union3> TemplatedClass1; // No warning expected
TemplatedClass<Tags3, Union4> TemplatedClass2;

// CHECK-MESSAGES: :[[@LINE+2]]:8: warning: tagged union has more data members (4) than tags (3)
template <typename T>
struct TemplatedStructButTaggedUnionPartIsNotTemplated {
Tags3 Kind;
Union4 Data;
T SomethingElse;
};

// CHECK-MESSAGES: :[[@LINE+2]]:7: warning: tagged union has more data members (4) than tags (3)
template <typename T>
class TemplatedClassButTaggedUnionPartIsNotTemplated {
Tags3 Kind;
Union4 Data;
T SomethingElse;
};

#define DECLARE_TAGGED_UNION_STRUCT(Tag, Union, Name)\
struct Name {\
Tag Kind;\
Union Data;\
}

// CHECK-MESSAGES: :[[@LINE+1]]:44: warning: tagged union has more data members (4) than tags (3)
DECLARE_TAGGED_UNION_STRUCT(Tags3, Union4, TaggedUnionStructFromMacro);

#define DECLARE_TAGGED_UNION_CLASS(Tag, Union, Name)\
class Name {\
Tag Kind;\
Union Data;\
}

// CHECK-MESSAGES: :[[@LINE+1]]:43: warning: tagged union has more data members (4) than tags (3)
DECLARE_TAGGED_UNION_CLASS(Tags3, Union4, TaggedUnionClassFromMacro);

// Lambdas implicitly compile down to an unnamed CXXRecordDecl and if they have captures,
// then those become unnamed fields.
void DoNotMatchLambdas() {
enum {
A
} e;
union {
long A;
char B;
} u;
auto L = [e, u] () {};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
// RUN: %check_clang_tidy %s bugprone-tagged-union-member-count %t

typedef enum Tags3 {
tags3_1,
tags3_2,
tags3_3,
} Tags3;

typedef enum Tags4 {
tags4_1,
tags4_2,
tags4_3,
tags4_4,
} Tags4;

typedef union Union3 {
short *Shorts;
int *Ints;
float *Floats;
} Union3;

typedef union Union4 {
short *Shorts;
double *Doubles;
int *Ints;
float *Floats;
} Union4;

// It is not obvious which enum is the tag for the union.
struct maybeTaggedUnion1 { // No warnings expected.
enum Tags3 TagA;
enum Tags4 TagB;
union Union4 Data;
};

// It is not obvious which union does the tag belong to.
struct maybeTaggedUnion2 { // No warnings expected.
enum Tags3 Tag;
union Union3 DataB;
union Union3 DataA;
};

// It is not obvious which union does the tag belong to.
struct maybeTaggedUnion3 { // No warnings expected.
enum Tags3 Tag;
union {
int I1;
int I2;
int I3;
};
union {
float F1;
float F2;
float F3;
};
};

// No warnings expected, because LastATag is just an alias
struct TaggedUnionWithAliasedEnumConstant {
enum {
ATag1,
ATag2,
ATag3,
LastATag = ATag3,
} Tag;
union {
float F;
int *Ints;
char Key[8];
} Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:8: warning: tagged union has more data members (4) than tags (3)
struct TaggedUnionStructWithPredefinedTagAndPredefinedUnion {
enum Tags3 Tag;
union Union4 Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:8: warning: tagged union has more data members (4) than tags (3)
struct TaggedUnionStructWithPredefinedTagAndInlineUnion {
enum Tags3 Tag;
union {
int *Ints;
char Characters[13];
struct {
double Re;
double Im;
} Complex;
long L;
} Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:8: warning: tagged union has more data members (4) than tags (3)
struct TaggedUnionStructWithInlineTagAndPredefinedUnion {
enum {
TaggedUnion7tag1,
TaggedUnion7tag2,
TaggedUnion7tag3,
} Tag;
union Union4 Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:8: warning: tagged union has more data members (4) than tags (3)
struct TaggedUnionStructWithInlineTagAndInlineUnion {
enum {
TaggedUnion8tag1,
TaggedUnion8tag2,
TaggedUnion8tag3,
} Tag;
union {
int *Ints;
char Characters[13];
struct {
double Re;
double Im;
} Complex;
long L;
} Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:8: warning: tagged union has more data members (4) than tags (3)
struct TaggedUnionStructNesting {
enum Tags3 Tag;
union {
float F;
int I;
long L;
// CHECK-MESSAGES: :[[@LINE+1]]:12: warning: tagged union has more data members (4) than tags (3)
struct innerdecl {
enum Tags3 Tag;
union Union4 Data;
} Inner;
} Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:8: warning: tagged union has more data members (4) than tags (3)
struct TaggedUnionStructWithTypedefedTagAndTypedefedUnion {
Tags3 Tag;
Union4 Data;
};

#define DECLARE_TAGGED_UNION_STRUCT(Tag, Union, Name)\
struct Name {\
Tag Kind;\
Union Data;\
}

// CHECK-MESSAGES: :[[@LINE+1]]:44: warning: tagged union has more data members (4) than tags (3)
DECLARE_TAGGED_UNION_STRUCT(Tags3, Union4, TaggedUnionStructFromMacro);
Original file line number Diff line number Diff line change
@@ -0,0 +1,309 @@
// RUN: %check_clang_tidy %s bugprone-tagged-union-member-count %t

typedef enum Tags3 {
tags3_1,
tags3_2,
tags3_3,
} Tags3;

typedef enum Tags4 {
tags4_1,
tags4_2,
tags4_3,
tags4_4,
} Tags4;

enum class Classtags3 {
classtags3_1,
classtags3_2,
classtags3_3,
};

enum class Typedtags3 : unsigned int {
typedtags3_1,
typedtags3_2,
typedtags3_3,
};

typedef union Union3 {
short *Shorts;
int *Ints;
float *Floats;
} Union3;

typedef union Union4 {
short *Shorts;
double *Doubles;
int *Ints;
float *Floats;
} Union4;

// It is not obvious which enum is the tag for the union.
class MaybeTaggedUnion1 { // No warnings expected.
enum Tags3 TagA;
enum Tags4 TagB;
union Union4 Data;
};

// It is not obvious which union does the tag belong to.
class MaybeTaggedUnion2 { // No warnings expected.
enum Tags3 Tag;
union Union3 DataB;
union Union3 DataA;
};

// It is not obvious which union does the tag belong to.
class MaybeTaggedUnion3 { // No warnings expected.
enum Tags3 Tag;
union {
int I1;
int I2;
int I3;
};
union {
float F1;
float F2;
float F3;
};
};

// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3)
class TaggedUnionClassPredefinedTagAndPredefinedUnion {
enum Tags3 Tag;
union Union4 Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3)
class TaggedUnionClassPredefinedTagAndInlineUnion {
enum Tags3 Tag;
union {
int *Ints;
char Characters[13];
class {
double Re;
double Im;
} Complex;
long L;
} Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3)
class TaggedUnionClassInlineTagAndPredefinedUnion {
enum {
tag1,
tag2,
tag3,
} Tag;
union Union4 Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3)
class TaggedUnionClassInlineTagAndInlineUnion {
enum {
tag1,
tag2,
tag3,
} Tag;
union {
int *Ints;
char Characters[13];
class {
double Re;
double Im;
} Complex;
long L;
} Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3)
class TaggedUnionClassWithNestedTaggedUnionClass {
enum Tags3 Tag;
union {
float F;
int I;
long L;
// CHECK-MESSAGES: :[[@LINE+1]]:11: warning: tagged union has more data members (4) than tags (3)
class Innerdecl {
enum Tags3 Tag;
union Union4 Data;
} Inner;
} Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3)
class TaggedUnionClassWithTypedefedTag {
Tags3 Tag;
Union4 Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:8: warning: tagged union has more data members (4) than tags (3)
struct TaggedUnionStructWithEnumClass {
enum Classtags3 Tag;
Union4 Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3)
class TaggedUnionClasswithEnumClass {
enum Classtags3 Tag;
Union4 Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:8: warning: tagged union has more data members (4) than tags (3)
struct TaggedUnionStructWithTypedEnum {
Typedtags3 Tag;
Union4 Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3)
class TaggedUnionClassWithTypedEnum {
Typedtags3 Tag;
Union4 Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:8: warning: tagged union has more data members (4) than tags (3)
struct AnonymousTaggedUnionStruct {
Tags3 Tag;
union {
char A;
short B;
int C;
long D;
};
};

// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3)
class TaggedUnionClassWithAnonymousUnion {
Tags3 Tag;
union {
char A;
short B;
int C;
long D;
};
};

namespace testnamespace {

enum Tags3 {
tags3_1,
tags3_2,
tags3_3,
};

union Union4 {
short *Shorts;
double *Doubles;
int *Ints;
float *Floats;
};

// CHECK-MESSAGES: :[[@LINE+1]]:8: warning: tagged union has more data members (4) than tags (3)
struct TaggedUnionStructInNamespace {
Tags3 Tags;
Union4 Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3)
class TaggedUnionClassInNamespace {
Tags3 Tags;
Union4 Data;
};

} // namespace testnamespace

// CHECK-MESSAGES: :[[@LINE+1]]:8: warning: tagged union has more data members (4) than tags (3)
struct TaggedUnionStructWithNamespacedTagAndUnion {
testnamespace::Tags3 Tags;
testnamespace::Union4 Data;
};

// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3)
class TaggedUnionClassWithNamespacedTagAndUnion {
testnamespace::Tags3 Tags;
testnamespace::Union4 Data;
};

// CHECK-MESSAGES: :[[@LINE+2]]:8: warning: tagged union has more data members (4) than tags (3)
template <typename Tag, typename Union>
struct TemplatedStructWithNamespacedTagAndUnion {
Tag Kind;
Union Data;
};

TemplatedStructWithNamespacedTagAndUnion<testnamespace::Union4, testnamespace::Tags3> TemplatedStruct3;

// CHECK-MESSAGES: :[[@LINE+2]]:7: warning: tagged union has more data members (4) than tags (3)
template <typename Tag, typename Union>
class TemplatedClassWithNamespacedTagAndUnion {
Tag Kind;
Union Data;
};

TemplatedClassWithNamespacedTagAndUnion<testnamespace::Union4, testnamespace::Tags3> TemplatedClass3;

// CHECK-MESSAGES: :[[@LINE+2]]:8: warning: tagged union has more data members (4) than tags (3)
template <typename Tag, typename Union>
struct TemplatedStruct {
Tag Kind;
Union Data;
};

TemplatedStruct<Tags3, Union3> TemplatedStruct1; // No warning expected
TemplatedStruct<Tags3, Union4> TemplatedStruct2;

// CHECK-MESSAGES: :[[@LINE+2]]:7: warning: tagged union has more data members (4) than tags (3)
template <typename Tag, typename Union>
class TemplatedClass {
Tag Kind;
Union Data;
};

TemplatedClass<Tags3, Union3> TemplatedClass1; // No warning expected
TemplatedClass<Tags3, Union4> TemplatedClass2;

// CHECK-MESSAGES: :[[@LINE+2]]:8: warning: tagged union has more data members (4) than tags (3)
template <typename T>
struct TemplatedStructButTaggedUnionPartIsNotTemplated {
Tags3 Kind;
Union4 Data;
T SomethingElse;
};

// CHECK-MESSAGES: :[[@LINE+2]]:7: warning: tagged union has more data members (4) than tags (3)
template <typename T>
class TemplatedClassButTaggedUnionPartIsNotTemplated {
Tags3 Kind;
Union4 Data;
T SomethingElse;
};

#define DECLARE_TAGGED_UNION_STRUCT(Tag, Union, Name)\
struct Name {\
Tag Kind;\
Union Data;\
}

// CHECK-MESSAGES: :[[@LINE+1]]:44: warning: tagged union has more data members (4) than tags (3)
DECLARE_TAGGED_UNION_STRUCT(Tags3, Union4, TaggedUnionStructFromMacro);

#define DECLARE_TAGGED_UNION_CLASS(Tag, Union, Name)\
class Name {\
Tag Kind;\
Union Data;\
}

// CHECK-MESSAGES: :[[@LINE+1]]:43: warning: tagged union has more data members (4) than tags (3)
DECLARE_TAGGED_UNION_CLASS(Tags3, Union4, TaggedUnionClassFromMacro);

// Lambdas implicitly compile down to an unnamed CXXRecordDecl and if they have captures,
// then those become unnamed fields.
void DoNotMatchLambdas() {
enum {
A
} e;
union {
long A;
char B;
} u;
auto L = [e, u] () {};
}
Original file line number Diff line number Diff line change
Expand Up @@ -980,3 +980,30 @@ namespace PR78381 {
}
}
}

namespace GH109083 {
void test() {
const int N = 6;
int Arr[N] = {1, 2, 3, 4, 5, 6};

for (int I = 0; I < N; ++I) {
auto V = [T = Arr[I]]() {};
}
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead [modernize-loop-convert]
// CHECK-FIXES: for (int I : Arr)
// CHECK-FIXES-NEXT: auto V = [T = I]() {};
for (int I = 0; I < N; ++I) {
auto V = [T = 10 + Arr[I]]() {};
}
// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead [modernize-loop-convert]
// CHECK-FIXES: for (int I : Arr)
// CHECK-FIXES-NEXT: auto V = [T = 10 + I]() {};

for (int I = 0; I < N; ++I) {
auto V = [T = I]() {};
}
for (int I = 0; I < N; ++I) {
auto V = [T = I + 10]() {};
}
}
} // namespace GH109083
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,11 @@
// CHECK-VERIFY-BLOCK-BAD: command-line option '-config': warning: check glob 'bugprone-arguments-*' doesn't match any known check [-verify-config]
// CHECK-VERIFY-BLOCK-BAD: command-line option '-config': warning: unknown check 'bugprone-assert-side-effects'; did you mean 'bugprone-assert-side-effect' [-verify-config]

// RUN: echo -e 'Checks: "-*,clang-analyzer-optin.cplusplus.UninitializedObject"\nCheckOptions:\n clang-analyzer-optin.cplusplus.UninitializedObject:Pedantic: true' > %T/MyClangTidyConfigCSA
// RUN: clang-tidy --verify-config --config-file=%T/MyClangTidyConfigCSA 2>&1 | FileCheck %s -check-prefix=CHECK-VERIFY-CSA-OK -implicit-check-not='{{warnings|error}}'
// CHECK-VERIFY-CSA-OK: No config errors detected.

// RUN: echo -e 'Checks: "-*,clang-analyzer-optin.cplusplus.UninitializedObject"\nCheckOptions:\n clang-analyzer-optin.cplusplus.UninitializedObject.Pedantic: true' > %T/MyClangTidyConfigCSABad
// RUN: not clang-tidy --verify-config --config-file=%T/MyClangTidyConfigCSABad 2>&1 | FileCheck %s -check-prefix=CHECK-VERIFY-CSA-BAD -implicit-check-not='{{warnings|error}}'
// CHECK-VERIFY-CSA-BAD: command-line option '-config': warning: unknown check option 'clang-analyzer-optin.cplusplus.UninitializedObject.Pedantic'; did you mean 'clang-analyzer-optin.cplusplus.UninitializedObject:Pedantic' [-verify-config]

44 changes: 20 additions & 24 deletions clang/CodeOwners.rst → clang/Maintainers.rst
Original file line number Diff line number Diff line change
@@ -1,36 +1,36 @@
=================
Clang Code Owners
Clang Maintainers
=================

This file is a list of the
`code owners <https://llvm.org/docs/DeveloperPolicy.html#code-owners>`_ for
`maintainers <https://llvm.org/docs/DeveloperPolicy.html#maintainers>`_ for
Clang.

.. contents::
:depth: 2
:local:

Current Code Owners
===================
The following people are the active code owners for the project. Please reach
Active Maintainers
==================
The following people are the active maintainers for the project. Please reach
out to them for code reviews, questions about their area of expertise, or other
assistance.

All parts of Clang not covered by someone else
----------------------------------------------
Lead Maintainer
---------------
| Aaron Ballman
| aaron\@aaronballman.com (email), aaron.ballman (Phabricator), AaronBallman (GitHub), AaronBallman (Discourse), aaronballman (Discord), AaronBallman (IRC)

Contained Components
--------------------
These code owners are responsible for particular high-level components within
These maintainers are responsible for particular high-level components within
Clang that are typically contained to one area of the compiler.

AST matchers
~~~~~~~~~~~~
| Manuel Klimek
| klimek\@google.com (email), klimek (Phabricator), r4nt (GitHub)
| Aaron Ballman
| aaron\@aaronballman.com (email), aaron.ballman (Phabricator), AaronBallman (GitHub), AaronBallman (Discourse), aaronballman (Discord), AaronBallman (IRC)

Clang LLVM IR generation
Expand Down Expand Up @@ -60,7 +60,7 @@ Analysis & CFG
Experimental new constant interpreter
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Timm Bäder
| tbaeder\@redhat.com (email), tbaeder (Phabricator), tbaederr (GitHub), tbaeder (Discourse), tbaeder (Discord)
| tbaeder\@redhat.com (em), tbaeder (Phabricator), tbaederr (GitHub), tbaeder (Discourse), tbaeder (Discord)

Modules & serialization
Expand Down Expand Up @@ -125,14 +125,9 @@ Driver parts not covered by someone else

Tools
-----
These code owners are responsible for user-facing tools under the Clang
These maintainers are responsible for user-facing tools under the Clang
umbrella or components used to support such tools.

Tooling library
~~~~~~~~~~~~~~~
| Manuel Klimek
| klimek\@google.com (email), klimek (Phabricator), r4nt (GitHub)

clang-format
~~~~~~~~~~~~
Expand Down Expand Up @@ -255,19 +250,20 @@ SYCL conformance
| alexey.bader\@intel.com (email), bader (Phabricator), bader (GitHub)

Former Code Owners
==================
The following people have graciously spent time performing code ownership
Inactive Maintainers
====================
The following people have graciously spent time performing maintainership
responsibilities but are no longer active in that role. Thank you for all your
help with the success of the project!

Emeritus owners
---------------
Emeritus Lead Maintainers
-------------------------
| Doug Gregor (dgregor\@apple.com)
| Richard Smith (richard\@metafoo.co.uk)

Former component owners
-----------------------
Inactive component maintainers
------------------------------
| Chandler Carruth (chandlerc\@gmail.com, chandlerc\@google.com) -- CMake, library layering
| Devin Coughlin (dcoughlin\@apple.com) -- Clang static analyzer
| Manuel Klimek (klimek\@google.com (email), klimek (Phabricator), r4nt (GitHub)) -- Tooling, AST matchers
3 changes: 3 additions & 0 deletions clang/cmake/caches/Release.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,6 @@ set_final_stage_var(LLVM_ENABLE_PROJECTS "${LLVM_RELEASE_ENABLE_PROJECTS}" STRIN
set_final_stage_var(CPACK_GENERATOR "TXZ" STRING)
set_final_stage_var(CPACK_ARCHIVE_THREADS "0" STRING)

if(${CMAKE_HOST_SYSTEM_NAME} MATCHES "Darwin")
set_final_stage_var(LLVM_USE_STATIC_ZSTD "ON" BOOL)
endif()
15 changes: 15 additions & 0 deletions clang/cmake/caches/hexagon-unknown-linux-musl-clang-cross.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# This file is for the llvm+clang options that are specific to building
# a cross-toolchain targeting hexagon linux.
set(DEFAULT_SYSROOT "../target/hexagon-unknown-linux-musl/" CACHE STRING "")
set(CLANG_LINKS_TO_CREATE
hexagon-linux-musl-clang++
hexagon-linux-musl-clang
hexagon-unknown-linux-musl-clang++
hexagon-unknown-linux-musl-clang
hexagon-none-elf-clang++
hexagon-none-elf-clang
hexagon-unknown-none-elf-clang++
hexagon-unknown-none-elf-clang
CACHE STRING "")

set(LLVM_INSTALL_TOOLCHAIN_ONLY ON CACHE BOOL "")
15 changes: 15 additions & 0 deletions clang/cmake/caches/hexagon-unknown-linux-musl-clang.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

set(LLVM_TARGETS_TO_BUILD "Hexagon" CACHE STRING "")
set(LLVM_DEFAULT_TARGET_TRIPLE "hexagon-unknown-linux-musl" CACHE STRING "")
set(CLANG_DEFAULT_CXX_STDLIB "libc++" CACHE STRING "")
set(CLANG_DEFAULT_OBJCOPY "llvm-objcopy" CACHE STRING "")
set(CLANG_DEFAULT_RTLIB "compiler-rt" CACHE STRING "")
set(CLANG_DEFAULT_UNWINDLIB "libunwind" CACHE STRING "")
set(CLANG_DEFAULT_LINKER "lld" CACHE STRING "")
set(LLVM_ENABLE_PROJECTS "clang;lld" CACHE STRING "")

set(LLVM_INCLUDE_TESTS OFF CACHE BOOL "")
set(LLVM_INCLUDE_DOCS OFF CACHE BOOL "")
# Enabling toolchain-only causes problems when doing some of the
# subsequent builds, will need to investigate:
set(LLVM_INSTALL_TOOLCHAIN_ONLY OFF CACHE BOOL "")
2 changes: 1 addition & 1 deletion clang/docs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ if (LLVM_ENABLE_SPHINX)
"${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}"

COMMAND "${CMAKE_COMMAND}" -E copy_if_different
"${CMAKE_CURRENT_SOURCE_DIR}/../CodeOwners.rst"
"${CMAKE_CURRENT_SOURCE_DIR}/../Maintainers.rst"
"${CMAKE_CURRENT_BINARY_DIR}"
)

Expand Down
193 changes: 157 additions & 36 deletions clang/docs/ClangFormatStyleOptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ the configuration (without a prefix: ``Auto``).
.. _AlignArrayOfStructures:

**AlignArrayOfStructures** (``ArrayInitializerAlignmentStyle``) :versionbadge:`clang-format 13` :ref:`¶ <AlignArrayOfStructures>`
if not ``None``, when using initialization for an array of structs
If not ``None``, when using initialization for an array of structs
aligns the fields into columns.


Expand Down Expand Up @@ -307,11 +307,12 @@ the configuration (without a prefix: ``Auto``).
Alignment options.

They can also be read as a whole for compatibility. The choices are:
- None
- Consecutive
- AcrossEmptyLines
- AcrossComments
- AcrossEmptyLinesAndComments

* ``None``
* ``Consecutive``
* ``AcrossEmptyLines``
* ``AcrossComments``
* ``AcrossEmptyLinesAndComments``

For example, to align across empty lines and not across comments, either
of these work.
Expand Down Expand Up @@ -392,6 +393,21 @@ the configuration (without a prefix: ``Auto``).
a &= 2;
bbb = 2;

* ``bool AlignFunctionDeclarations`` Only for ``AlignConsecutiveDeclarations``. Whether function declarations
are aligned.

.. code-block:: c++

true:
unsigned int f1(void);
void f2(void);
size_t f3(void);

false:
unsigned int f1(void);
void f2(void);
size_t f3(void);

* ``bool AlignFunctionPointers`` Only for ``AlignConsecutiveDeclarations``. Whether function pointers are
aligned.

Expand Down Expand Up @@ -449,11 +465,12 @@ the configuration (without a prefix: ``Auto``).
Alignment options.

They can also be read as a whole for compatibility. The choices are:
- None
- Consecutive
- AcrossEmptyLines
- AcrossComments
- AcrossEmptyLinesAndComments

* ``None``
* ``Consecutive``
* ``AcrossEmptyLines``
* ``AcrossComments``
* ``AcrossEmptyLinesAndComments``

For example, to align across empty lines and not across comments, either
of these work.
Expand Down Expand Up @@ -534,6 +551,21 @@ the configuration (without a prefix: ``Auto``).
a &= 2;
bbb = 2;

* ``bool AlignFunctionDeclarations`` Only for ``AlignConsecutiveDeclarations``. Whether function declarations
are aligned.

.. code-block:: c++

true:
unsigned int f1(void);
void f2(void);
size_t f3(void);

false:
unsigned int f1(void);
void f2(void);
size_t f3(void);

* ``bool AlignFunctionPointers`` Only for ``AlignConsecutiveDeclarations``. Whether function pointers are
aligned.

Expand Down Expand Up @@ -591,11 +623,12 @@ the configuration (without a prefix: ``Auto``).
Alignment options.

They can also be read as a whole for compatibility. The choices are:
- None
- Consecutive
- AcrossEmptyLines
- AcrossComments
- AcrossEmptyLinesAndComments

* ``None``
* ``Consecutive``
* ``AcrossEmptyLines``
* ``AcrossComments``
* ``AcrossEmptyLinesAndComments``

For example, to align across empty lines and not across comments, either
of these work.
Expand Down Expand Up @@ -676,6 +709,21 @@ the configuration (without a prefix: ``Auto``).
a &= 2;
bbb = 2;

* ``bool AlignFunctionDeclarations`` Only for ``AlignConsecutiveDeclarations``. Whether function declarations
are aligned.

.. code-block:: c++

true:
unsigned int f1(void);
void f2(void);
size_t f3(void);

false:
unsigned int f1(void);
void f2(void);
size_t f3(void);

* ``bool AlignFunctionPointers`` Only for ``AlignConsecutiveDeclarations``. Whether function pointers are
aligned.

Expand Down Expand Up @@ -734,11 +782,12 @@ the configuration (without a prefix: ``Auto``).
Alignment options.

They can also be read as a whole for compatibility. The choices are:
- None
- Consecutive
- AcrossEmptyLines
- AcrossComments
- AcrossEmptyLinesAndComments

* ``None``
* ``Consecutive``
* ``AcrossEmptyLines``
* ``AcrossComments``
* ``AcrossEmptyLinesAndComments``

For example, to align across empty lines and not across comments, either
of these work.
Expand Down Expand Up @@ -819,6 +868,21 @@ the configuration (without a prefix: ``Auto``).
a &= 2;
bbb = 2;

* ``bool AlignFunctionDeclarations`` Only for ``AlignConsecutiveDeclarations``. Whether function declarations
are aligned.

.. code-block:: c++

true:
unsigned int f1(void);
void f2(void);
size_t f3(void);

false:
unsigned int f1(void);
void f2(void);
size_t f3(void);

* ``bool AlignFunctionPointers`` Only for ``AlignConsecutiveDeclarations``. Whether function pointers are
aligned.

Expand Down Expand Up @@ -996,11 +1060,12 @@ the configuration (without a prefix: ``Auto``).
Alignment options.

They can also be read as a whole for compatibility. The choices are:
- None
- Consecutive
- AcrossEmptyLines
- AcrossComments
- AcrossEmptyLinesAndComments

* ``None``
* ``Consecutive``
* ``AcrossEmptyLines``
* ``AcrossComments``
* ``AcrossEmptyLinesAndComments``

For example, to align across empty lines and not across comments, either
of these work.
Expand Down Expand Up @@ -1081,6 +1146,21 @@ the configuration (without a prefix: ``Auto``).
a &= 2;
bbb = 2;

* ``bool AlignFunctionDeclarations`` Only for ``AlignConsecutiveDeclarations``. Whether function declarations
are aligned.

.. code-block:: c++

true:
unsigned int f1(void);
void f2(void);
size_t f3(void);

false:
unsigned int f1(void);
void f2(void);
size_t f3(void);

* ``bool AlignFunctionPointers`` Only for ``AlignConsecutiveDeclarations``. Whether function pointers are
aligned.

Expand Down Expand Up @@ -1136,11 +1216,12 @@ the configuration (without a prefix: ``Auto``).
Alignment options.

They can also be read as a whole for compatibility. The choices are:
- None
- Consecutive
- AcrossEmptyLines
- AcrossComments
- AcrossEmptyLinesAndComments

* ``None``
* ``Consecutive``
* ``AcrossEmptyLines``
* ``AcrossComments``
* ``AcrossEmptyLinesAndComments``

For example, to align across empty lines and not across comments, either
of these work.
Expand Down Expand Up @@ -1221,6 +1302,21 @@ the configuration (without a prefix: ``Auto``).
a &= 2;
bbb = 2;

* ``bool AlignFunctionDeclarations`` Only for ``AlignConsecutiveDeclarations``. Whether function declarations
are aligned.

.. code-block:: c++

true:
unsigned int f1(void);
void f2(void);
size_t f3(void);

false:
unsigned int f1(void);
void f2(void);
size_t f3(void);

* ``bool AlignFunctionPointers`` Only for ``AlignConsecutiveDeclarations``. Whether function pointers are
aligned.

Expand Down Expand Up @@ -1276,11 +1372,12 @@ the configuration (without a prefix: ``Auto``).
Alignment options.

They can also be read as a whole for compatibility. The choices are:
- None
- Consecutive
- AcrossEmptyLines
- AcrossComments
- AcrossEmptyLinesAndComments

* ``None``
* ``Consecutive``
* ``AcrossEmptyLines``
* ``AcrossComments``
* ``AcrossEmptyLinesAndComments``

For example, to align across empty lines and not across comments, either
of these work.
Expand Down Expand Up @@ -1361,6 +1458,21 @@ the configuration (without a prefix: ``Auto``).
a &= 2;
bbb = 2;

* ``bool AlignFunctionDeclarations`` Only for ``AlignConsecutiveDeclarations``. Whether function declarations
are aligned.

.. code-block:: c++

true:
unsigned int f1(void);
void f2(void);
size_t f3(void);

false:
unsigned int f1(void);
void f2(void);
size_t f3(void);

* ``bool AlignFunctionPointers`` Only for ``AlignConsecutiveDeclarations``. Whether function pointers are
aligned.

Expand Down Expand Up @@ -6554,6 +6666,15 @@ the configuration (without a prefix: ``Auto``).
let DAGArgOtherID = (other i32:$other1, i32:$other2);
let DAGArgBang = (!cast<SomeType>("Some") i32:$src1, i32:$src2)

.. _TemplateNames:

**TemplateNames** (``List of Strings``) :versionbadge:`clang-format 20` :ref:`¶ <TemplateNames>`
A vector of non-keyword identifiers that should be interpreted as
template names.

A ``<`` after a template name is annotated as a template opener instead of
a binary operator.

.. _TypeNames:

**TypeNames** (``List of Strings``) :versionbadge:`clang-format 17` :ref:`¶ <TypeNames>`
Expand Down
1 change: 0 additions & 1 deletion clang/docs/CodeOwners.rst

This file was deleted.

167 changes: 94 additions & 73 deletions clang/docs/LanguageExtensions.rst

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions clang/docs/Maintainers.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.. include:: ../Maintainers.rst
4 changes: 2 additions & 2 deletions clang/docs/Multilib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,8 @@ For a more comprehensive example see
# If there is no multilib available for a particular set of flags, and the
# other multilibs are not adequate fallbacks, then you can define a variant
# record with a FatalError key in place of the Dir key.
- FatalError: this multilib collection has no hard-float ABI support
# record with an Error key in place of the Dir key.
- Error: this multilib collection has no hard-float ABI support
Flags: [--target=thumbv7m-none-eabi, -mfloat-abi=hard]
Expand Down
150 changes: 130 additions & 20 deletions clang/docs/RealtimeSanitizer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Introduction
============
RealtimeSanitizer (a.k.a. RTSan) is a real-time safety testing tool for C and C++
projects. RTSan can be used to detect real-time violations, i.e. calls to methods
that are not safe for use in functions with deterministic runtime requirements.
that are not safe for use in functions with deterministic run time requirements.
RTSan considers any function marked with the ``[[clang::nonblocking]]`` attribute
to be a real-time function. If RTSan detects a call to ``malloc``, ``free``,
``pthread_mutex_lock``, or anything else that could have a non-deterministic
Expand Down Expand Up @@ -58,38 +58,148 @@ code.
return 0;
}
# Compile and link
% clang++ -fsanitize=realtime -g example_realtime_violation.cpp
% clang++ -fsanitize=realtime example_realtime_violation.cpp
If a real-time safety violation is detected in a ``[[clang::nonblocking]]``
context, or any function invoked by that function, the program will exit with a
non-zero exit code.

.. code-block:: console
% clang++ -fsanitize=realtime -g example_realtime_violation.cpp
% clang++ -fsanitize=realtime example_realtime_violation.cpp
% ./a.out
Real-time violation: intercepted call to real-time unsafe function `malloc` in real-time context! Stack trace:
#0 0x000102893034 in __rtsan::PrintStackTrace() rtsan_stack.cpp:45
#1 0x000102892e64 in __rtsan::Context::ExpectNotRealtime(char const*) rtsan_context.cpp:78
#2 0x00010289397c in malloc rtsan_interceptors.cpp:286
#3 0x000195bd7bd0 in operator new(unsigned long)+0x1c (libc++abi.dylib:arm64+0x16bd0)
#4 0x5c7f00010230f07c (<unknown module>)
#5 0x00010230f058 in std::__1::__libcpp_allocate[abi:ue170006](unsigned long, unsigned long) new:324
#6 0x00010230effc in std::__1::allocator<float>::allocate[abi:ue170006](unsigned long) allocator.h:114
... snip ...
#10 0x00010230e4bc in std::__1::vector<float, std::__1::allocator<float>>::__append(unsigned long) vector:1162
#11 0x00010230dcdc in std::__1::vector<float, std::__1::allocator<float>>::resize(unsigned long) vector:1981
#12 0x00010230dc28 in violation() main.cpp:5
#13 0x00010230dd64 in main main.cpp:9
#14 0x0001958960dc (<unknown module>)
#15 0x2f557ffffffffffc (<unknown module>)
==76290==ERROR: RealtimeSanitizer: unsafe-library-call
Intercepted call to real-time unsafe function `malloc` in real-time context!
#0 0x000102a7b884 in malloc rtsan_interceptors.cpp:426
#1 0x00019c326bd0 in operator new(unsigned long)+0x1c (libc++abi.dylib:arm64+0x16bd0)
#2 0xa30d0001024f79a8 (<unknown module>)
#3 0x0001024f794c in std::__1::__libcpp_allocate[abi:ne200000](unsigned long, unsigned long)+0x44
#4 0x0001024f78c4 in std::__1::allocator<float>::allocate[abi:ne200000](unsigned long)+0x44
... snip ...
#9 0x0001024f6868 in std::__1::vector<float, std::__1::allocator<float>>::resize(unsigned long)+0x48
#10 0x0001024f67b4 in violation()+0x24
#11 0x0001024f68f0 in main+0x18 (a.out:arm64+0x1000028f0)
#12 0x00019bfe3150 (<unknown module>)
#13 0xed5efffffffffffc (<unknown module>)
Blocking functions
------------------

Calls to system library functions such as ``malloc`` are automatically caught by
RealtimeSanitizer. Real-time programmers may also write their own blocking
(real-time unsafe) functions that they wish RealtimeSanitizer to be aware of.
RealtimeSanitizer will raise an error at run time if any function attributed
with ``[[clang::blocking]]`` is called in a ``[[clang::nonblocking]]`` context.

.. code-block:: console
$ cat example_blocking_violation.cpp
#include <atomic>
#include <thread>
std::atomic<bool> has_permission{false};
int wait_for_permission() [[clang::blocking]] {
while (has_permission.load() == false)
std::this_thread::yield();
return 0;
}
int real_time_function() [[clang::nonblocking]] {
return wait_for_permission();
}
int main() {
return real_time_function();
}
$ clang++ -fsanitize=realtime example_blocking_violation.cpp && ./a.out
==76131==ERROR: RealtimeSanitizer: blocking-call
Call to blocking function `wait_for_permission()` in real-time context!
#0 0x0001000c3db0 in wait_for_permission()+0x10 (a.out:arm64+0x100003db0)
#1 0x0001000c3e3c in real_time_function()+0x10 (a.out:arm64+0x100003e3c)
#2 0x0001000c3e68 in main+0x10 (a.out:arm64+0x100003e68)
#3 0x00019bfe3150 (<unknown module>)
#4 0x5a27fffffffffffc (<unknown module>)
Run-time flags
--------------

RealtimeSanitizer supports a number of run-time flags, which can be specified in the ``RTSAN_OPTIONS`` environment variable:

.. code-block:: console
% RTSAN_OPTIONS=option_1=true:path_option_2="/some/file.txt" ./a.out
...
Or at compile-time by providing the symbol ``__rtsan_default_options``:

.. code-block:: c
__attribute__((__visibility__("default")))
extern "C" const char *__rtsan_default_options() {
return "symbolize=false:abort_on_error=0:log_to_syslog=0";
}
You can see all sanitizer options (some of which are unsupported) by using the ``help`` flag:

.. code-block:: console
% RTSAN_OPTIONS=help=true ./a.out
A **partial** list of flags RealtimeSanitizer respects:

.. list-table:: Run-time Flags
:widths: 20 10 10 70
:header-rows: 1

* - Flag name
- Default value
- Type
- Short description
* - ``halt_on_error``
- ``true``
- boolean
- Exit after first reported error. If false (continue after a detected error), deduplicates error stacks so errors appear only once.
* - ``print_stats_on_exit``
- ``false``
- boolean
- Print stats on exit. Includes total and unique errors.
* - ``color``
- ``"auto"``
- string
- Colorize reports: (always|never|auto).
* - ``fast_unwind_on_fatal``
- ``false``
- boolean
- If available, use the fast frame-pointer-based unwinder on detected errors. If true, ensure the code under test has been compiled with frame pointers with ``-fno-omit-frame-pointers`` or similar.
* - ``abort_on_error``
- OS dependent
- boolean
- If true, the tool calls abort() instead of _exit() after printing the error report. On some OSes (OSX, for exmple) this is beneficial because a better stack trace is emitted on crash.
* - ``symbolize``
- ``true``
- boolean
- If set, use the symbolizer to turn virtual addresses to file/line locations. If false, can greatly speed up the error reporting.


Some issues with flags can be debugged using the ``verbosity=$NUM`` flag:

.. code-block:: console
% RTSAN_OPTIONS=verbosity=1:misspelled_flag=true ./a.out
WARNING: found 1 unrecognized flag(s):
misspelled_flag
...
Disabling
---------

In some circumstances, you may want to suppress error reporting in a specific scope.

In C++, this is achieved via ``__rtsan::ScopedDisabler``. Within the scope where the ``ScopedDisabler`` object is instantiated, all sanitizer error reports are suppressed. This suppression applies to the current scope as well as all invoked functions, including any functions called transitively.
In C++, this is achieved via ``__rtsan::ScopedDisabler``. Within the scope where the ``ScopedDisabler`` object is instantiated, all sanitizer error reports are suppressed. This suppression applies to the current scope as well as all invoked functions, including any functions called transitively.

.. code-block:: c++

Expand All @@ -104,7 +214,7 @@ In C++, this is achieved via ``__rtsan::ScopedDisabler``. Within the scope wher

If RealtimeSanitizer is not enabled at compile time (i.e., the code is not compiled with the ``-fsanitize=realtime`` flag), the ``ScopedDisabler`` is compiled as a no-op.

In C, you can use the ``__rtsan_disable()`` and ``rtsan_enable()`` functions to manually disable and re-enable RealtimeSanitizer checks.
In C, you can use the ``__rtsan_disable()`` and ``rtsan_enable()`` functions to manually disable and re-enable RealtimeSanitizer checks.

.. code-block:: c++

Expand Down
59 changes: 59 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ ABI Changes in This Version

- Fixed Microsoft name mangling of placeholder, auto and decltype(auto), return types for MSVC 1920+. This change resolves incompatibilities with code compiled by MSVC 1920+ but will introduce incompatibilities with code compiled by earlier versions of Clang unless such code is built with the compiler option -fms-compatibility-version=19.14 to imitate the MSVC 1914 mangling behavior.
- Fixed the Itanium mangling of the construction vtable name. This change will introduce incompatibilities with code compiled by Clang 19 and earlier versions, unless the -fclang-abi-compat=19 option is used. (#GH108015)
- Mangle member-like friend function templates as members of the enclosing class. (#GH110247, #GH110503)

AST Dumping Potentially Breaking Changes
----------------------------------------
Expand Down Expand Up @@ -144,6 +145,9 @@ C++ Language Changes

- Add ``__builtin_elementwise_fmod`` builtin for floating point types only.

- Add ``__builtin_elementwise_minimum`` and ``__builtin_elementwise_maximum``
builtin for floating point types only.

- The builtin type alias ``__builtin_common_type`` has been added to improve the
performance of ``std::common_type``.

Expand All @@ -170,6 +174,10 @@ C++23 Feature Support
C++20 Feature Support
^^^^^^^^^^^^^^^^^^^^^

C++17 Feature Support
^^^^^^^^^^^^^^^^^^^^^
- The implementation of the relaxed template template argument matching rules is
more complete and reliable, and should provide more accurate diagnostics.

Resolutions to C++ Defect Reports
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -205,6 +213,9 @@ Resolutions to C++ Defect Reports
- Reject explicit object parameters with type ``void`` (``this void``).
(`CWG2915: Explicit object parameters of type void <https://cplusplus.github.io/CWG/issues/2915.html>`_).

- Clang now allows trailing requires clause on explicit deduction guides.
(`CWG2707: Deduction guides cannot have a trailing requires-clause <https://cplusplus.github.io/CWG/issues/2707.html>`_).

C Language Changes
------------------

Expand Down Expand Up @@ -324,6 +335,10 @@ Improvements to Clang's diagnostics

- Clang now diagnoses when the result of a [[nodiscard]] function is discarded after being cast in C. Fixes #GH104391.

- Clang now properly explains the reason a template template argument failed to
match a template template parameter, in terms of the C++17 relaxed matching rules
instead of the old ones.

- Don't emit duplicated dangling diagnostics. (#GH93386).

- Improved diagnostic when trying to befriend a concept. (#GH45182).
Expand Down Expand Up @@ -359,6 +374,12 @@ Improvements to Clang's diagnostics

- Clang now diagnoses cases where a dangling ``GSLOwner<GSLPointer>`` object is constructed, e.g. ``std::vector<string_view> v = {std::string()};`` (#GH100526).

- Clang now diagnoses when a ``requires`` expression has a local parameter of void type, aligning with the function parameter (#GH109831).

- Clang now emits a diagnostic note at the class declaration when the method definition does not match any declaration (#GH110638).

- Clang now omits warnings for extra parentheses in fold expressions with single expansion (#GH101863).

Improvements to Clang's time-trace
----------------------------------

Expand All @@ -374,6 +395,8 @@ Bug Fixes in This Version
- Fixed a crash when trying to transform a dependent address space type. Fixes #GH101685.
- Fixed a crash when diagnosing format strings and encountering an empty
delimited escape sequence (e.g., ``"\o{}"``). #GH102218
- The warning emitted for an unsupported register variable type now points to
the unsupported type instead of the ``register`` keyword (#GH109776).

Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -419,6 +442,8 @@ Bug Fixes to C++ Support
- Correctly check constraints of explicit instantiations of member functions. (#GH46029)
- When performing partial ordering of function templates, clang now checks that
the deduction was consistent. Fixes (#GH18291).
- Fixes to several issues in partial ordering of template template parameters, which
were documented in the test suite.
- Fixed an assertion failure about a constraint of a friend function template references to a value with greater
template depth than the friend function template. (#GH98258)
- Clang now rebuilds the template parameters of out-of-line declarations and specializations in the context
Expand Down Expand Up @@ -447,6 +472,13 @@ Bug Fixes to C++ Support
- Fixed an assertion failure in debug mode, and potential crashes in release mode, when
diagnosing a failed cast caused indirectly by a failed implicit conversion to the type of the constructor parameter.
- Fixed an assertion failure by adjusting integral to boolean vector conversions (#GH108326)
- Fixed an issue deducing non-type template arguments of reference type. (#GH73460)
- Fixed an issue in constraint evaluation, where type constraints on the lambda expression
containing outer unexpanded parameters were not correctly expanded. (#GH101754)
- Fixes crashes with function template member specializations, and increases
conformance of explicit instantiation behaviour with MSVC. (#GH111266)
- Fixed a bug in constraint expression comparison where the ``sizeof...`` expression was not handled properly
in certain friend declarations. (#GH93099)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -484,6 +516,10 @@ OpenACC Specific Changes
Target Specific Changes
-----------------------

- Clang now implements the Solaris-specific mangling of ``std::tm`` as
``tm``, same for ``std::div_t``, ``std::ldiv_t``, and
``std::lconv``, for Solaris ABI compatibility. (#GH33114)

AMDGPU Support
^^^^^^^^^^^^^^

Expand All @@ -510,6 +546,18 @@ X86 Support
* Supported MINMAX intrinsics of ``*_(mask(z)))_minmax(ne)_p[s|d|h|bh]`` and
``*_(mask(z)))_minmax_s[s|d|h]``.

- All intrinsics in adcintrin.h can now be used in constant expressions.

- All intrinsics in adxintrin.h can now be used in constant expressions.

- All intrinsics in lzcntintrin.h can now be used in constant expressions.

- All intrinsics in bmiintrin.h can now be used in constant expressions.

- All intrinsics in bmi2intrin.h can now be used in constant expressions.

- All intrinsics in tbmintrin.h can now be used in constant expressions.

Arm and AArch64 Support
^^^^^^^^^^^^^^^^^^^^^^^

Expand Down Expand Up @@ -557,6 +605,8 @@ DWARF Support in Clang
Floating Point Support in Clang
-------------------------------

- Add ``__builtin_elementwise_atan2`` builtin for floating point types only.

Fixed Point Support in Clang
----------------------------

Expand All @@ -575,6 +625,8 @@ clang-format
------------

- Adds ``BreakBinaryOperations`` option.
- Adds ``TemplateNames`` option.
- Adds ``AlignFunctionDeclarations`` option to ``AlignConsecutiveDeclarations``.

libclang
--------
Expand All @@ -587,11 +639,18 @@ Static Analyzer
New features
^^^^^^^^^^^^

- Now CSA models `__builtin_*_overflow` functions. (#GH102602)

- MallocChecker now checks for ``ownership_returns(class, idx)`` and ``ownership_takes(class, idx)``
attributes with class names different from "malloc". Clang static analyzer now reports an error
if class of allocation and deallocation function mismatches.
`Documentation <https://clang.llvm.org/docs/analyzer/checkers.html#unix-mismatcheddeallocator-c-c>`__.

- Function effects, e.g. the ``nonblocking`` and ``nonallocating`` "performance constraint"
attributes, are now verified. For example, for functions declared with the ``nonblocking``
attribute, the compiler can generate warnings about the use of any language features, or calls to
other functions, which may block.

Crash and bug fixes
^^^^^^^^^^^^^^^^^^^

Expand Down
114 changes: 71 additions & 43 deletions clang/docs/analyzer/checkers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1288,6 +1288,34 @@ by explicitly marking the ``size`` parameter as sanitized. See the
delete[] ptr;
}
.. _optin-taint-TaintedDiv:
optin.taint.TaintedDiv (C, C++, ObjC)
"""""""""""""""""""""""""""""""""""""
This checker warns when the denominator in a division
operation is a tainted (potentially attacker controlled) value.
If the attacker can set the denominator to 0, a runtime error can
be triggered. The checker warns when the denominator is a tainted
value and the analyzer cannot prove that it is not 0. This warning
is more pessimistic than the :ref:`core-DivideZero` checker
which warns only when it can prove that the denominator is 0.
.. code-block:: c
int vulnerable(int n) {
size_t size = 0;
scanf("%zu", &size);
return n / size; // warn: Division by a tainted value, possibly zero
}
int not_vulnerable(int n) {
size_t size = 0;
scanf("%zu", &size);
if (!size)
return 0;
return n / size; // no warning
}
.. _security-checkers:
security
Expand Down Expand Up @@ -1544,6 +1572,49 @@ Warn on ``mmap()`` calls with both writable and executable access.
// code
}
.. _security-PointerSub:
security.PointerSub (C)
"""""""""""""""""""""""
Check for pointer subtractions on two pointers pointing to different memory
chunks. According to the C standard §6.5.6 only subtraction of pointers that
point into (or one past the end) the same array object is valid (for this
purpose non-array variables are like arrays of size 1). This checker only
searches for different memory objects at subtraction, but does not check if the
array index is correct. Furthermore, only cases are reported where
stack-allocated objects are involved (no warnings on pointers to memory
allocated by `malloc`).
.. code-block:: c
void test() {
int a, b, c[10], d[10];
int x = &c[3] - &c[1];
x = &d[4] - &c[1]; // warn: 'c' and 'd' are different arrays
x = (&a + 1) - &a;
x = &b - &a; // warn: 'a' and 'b' are different variables
}
struct S {
int x[10];
int y[10];
};
void test1() {
struct S a[10];
struct S b;
int d = &a[4] - &a[6];
d = &a[0].x[3] - &a[0].x[1];
d = a[0].y - a[0].x; // warn: 'S.b' and 'S.a' are different objects
d = (char *)&b.y - (char *)&b.x; // warn: different members of the same object
d = (char *)&b.y - (char *)&b; // warn: object of type S is not the same array as a member of it
}
There may be existing applications that use code like above for calculating
offsets of members in a structure, using pointer subtractions. This is still
undefined behavior according to the standard and code like this can be replaced
with the `offsetof` macro.
.. _security-putenv-stack-array:
security.PutenvStackArray (C)
Expand Down Expand Up @@ -2761,49 +2832,6 @@ Check for pointer arithmetic on locations other than array elements.
p = &x + 1; // warn
}
.. _alpha-core-PointerSub:
alpha.core.PointerSub (C)
"""""""""""""""""""""""""
Check for pointer subtractions on two pointers pointing to different memory
chunks. According to the C standard §6.5.6 only subtraction of pointers that
point into (or one past the end) the same array object is valid (for this
purpose non-array variables are like arrays of size 1). This checker only
searches for different memory objects at subtraction, but does not check if the
array index is correct. Furthermore, only cases are reported where
stack-allocated objects are involved (no warnings on pointers to memory
allocated by `malloc`).
.. code-block:: c
void test() {
int a, b, c[10], d[10];
int x = &c[3] - &c[1];
x = &d[4] - &c[1]; // warn: 'c' and 'd' are different arrays
x = (&a + 1) - &a;
x = &b - &a; // warn: 'a' and 'b' are different variables
}
struct S {
int x[10];
int y[10];
};
void test1() {
struct S a[10];
struct S b;
int d = &a[4] - &a[6];
d = &a[0].x[3] - &a[0].x[1];
d = a[0].y - a[0].x; // warn: 'S.b' and 'S.a' are different objects
d = (char *)&b.y - (char *)&b.x; // warn: different members of the same object
d = (char *)&b.y - (char *)&b; // warn: object of type S is not the same array as a member of it
}
There may be existing applications that use code like above for calculating
offsets of members in a structure, using pointer subtractions. This is still
undefined behavior according to the standard and code like this can be replaced
with the `offsetof` macro.
.. _alpha-core-StackAddressAsyncEscape:
alpha.core.StackAddressAsyncEscape (ObjC)
Expand Down
2 changes: 1 addition & 1 deletion clang/docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ Design Documents
.. toctree::
:maxdepth: 1

CodeOwners
Maintainers
InternalsManual
DriverInternals
Multilib
Expand Down
68 changes: 56 additions & 12 deletions clang/include/clang/AST/APValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -314,51 +314,95 @@ class APValue {
DataType Data;

public:
/// Creates an empty APValue of type None.
APValue() : Kind(None) {}
/// Creates an integer APValue holding the given value.
explicit APValue(APSInt I) : Kind(None) {
MakeInt(); setInt(std::move(I));
}
/// Creates a float APValue holding the given value.
explicit APValue(APFloat F) : Kind(None) {
MakeFloat(); setFloat(std::move(F));
}
/// Creates a fixed-point APValue holding the given value.
explicit APValue(APFixedPoint FX) : Kind(None) {
MakeFixedPoint(std::move(FX));
}
/// Creates a vector APValue with \p N elements. The elements
/// are read from \p E.
explicit APValue(const APValue *E, unsigned N) : Kind(None) {
MakeVector(); setVector(E, N);
}
/// Creates an integer complex APValue with the given real and imaginary
/// values.
APValue(APSInt R, APSInt I) : Kind(None) {
MakeComplexInt(); setComplexInt(std::move(R), std::move(I));
}
/// Creates a float complex APValue with the given real and imaginary values.
APValue(APFloat R, APFloat I) : Kind(None) {
MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I));
}
APValue(const APValue &RHS);
APValue(APValue &&RHS);
APValue(LValueBase B, const CharUnits &O, NoLValuePath N,
/// Creates an lvalue APValue without an lvalue path.
/// \param Base The base of the lvalue.
/// \param Offset The offset of the lvalue.
/// \param IsNullPtr Whether this lvalue is a null pointer.
APValue(LValueBase Base, const CharUnits &Offset, NoLValuePath,
bool IsNullPtr = false)
: Kind(None) {
MakeLValue(); setLValue(B, O, N, IsNullPtr);
}
APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path,
bool OnePastTheEnd, bool IsNullPtr = false)
MakeLValue();
setLValue(Base, Offset, NoLValuePath{}, IsNullPtr);
}
/// Creates an lvalue APValue with an lvalue path.
/// \param Base The base of the lvalue.
/// \param Offset The offset of the lvalue.
/// \param Path The lvalue path.
/// \param OnePastTheEnd Whether this lvalue is one-past-the-end of the
/// subobject it points to.
/// \param IsNullPtr Whether this lvalue is a null pointer.
APValue(LValueBase Base, const CharUnits &Offset,
ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd,
bool IsNullPtr = false)
: Kind(None) {
MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr);
}
MakeLValue();
setLValue(Base, Offset, Path, OnePastTheEnd, IsNullPtr);
}
/// Creates a new array APValue.
/// \param UninitArray Marker. Pass an empty UninitArray.
/// \param InitElts Number of elements you're going to initialize in the
/// array.
/// \param Size Full size of the array.
APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(None) {
MakeArray(InitElts, Size);
}
APValue(UninitStruct, unsigned B, unsigned M) : Kind(None) {
MakeStruct(B, M);
}
explicit APValue(const FieldDecl *D, const APValue &V = APValue())
/// Creates a new struct APValue.
/// \param UninitStruct Marker. Pass an empty UninitStruct.
/// \param NumBases Number of bases.
/// \param NumMembers Number of members.
APValue(UninitStruct, unsigned NumBases, unsigned NumMembers) : Kind(None) {
MakeStruct(NumBases, NumMembers);
}
/// Creates a new union APValue.
/// \param ActiveDecl The FieldDecl of the active union member.
/// \param ActiveValue The value of the active union member.
explicit APValue(const FieldDecl *ActiveDecl,
const APValue &ActiveValue = APValue())
: Kind(None) {
MakeUnion(); setUnion(D, V);
MakeUnion();
setUnion(ActiveDecl, ActiveValue);
}
/// Creates a new member pointer APValue.
/// \param Member Declaration of the member
/// \param IsDerivedMember Whether member is a derived one.
/// \param Path The path of the member.
APValue(const ValueDecl *Member, bool IsDerivedMember,
ArrayRef<const CXXRecordDecl*> Path) : Kind(None) {
MakeMemberPointer(Member, IsDerivedMember, Path);
}
/// Creates a new address label diff APValue.
/// \param LHSExpr The left-hand side of the difference.
/// \param RHSExpr The right-hand side of the difference.
APValue(const AddrLabelExpr* LHSExpr, const AddrLabelExpr* RHSExpr)
: Kind(None) {
MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr);
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -1205,7 +1205,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
#include "clang/Basic/RISCVVTypes.def"
#define WASM_TYPE(Name, Id, SingletonId) CanQualType SingletonId;
#include "clang/Basic/WebAssemblyReferenceTypes.def"
#define AMDGPU_TYPE(Name, Id, SingletonId) CanQualType SingletonId;
#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) \
CanQualType SingletonId;
#include "clang/Basic/AMDGPUTypes.def"
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) CanQualType SingletonId;
#include "clang/Basic/HLSLIntangibleTypes.def"
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/AST/CanonicalType.h
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ class CanProxyBase {
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDependentType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isOverloadableType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArrayType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isConstantArrayType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasPointerRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasObjCPointerRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasIntegerRepresentation)
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/AST/ComputeDependence.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ class ObjCSubscriptRefExpr;
class ObjCIsaExpr;
class ObjCIndirectCopyRestoreExpr;
class ObjCMessageExpr;
class OpenACCAsteriskSizeExpr;

// The following functions are called from constructors of `Expr`, so they
// should not access anything beyond basic
Expand Down Expand Up @@ -203,6 +204,7 @@ ExprDependence computeDependence(ObjCSubscriptRefExpr *E);
ExprDependence computeDependence(ObjCIsaExpr *E);
ExprDependence computeDependence(ObjCIndirectCopyRestoreExpr *E);
ExprDependence computeDependence(ObjCMessageExpr *E);
ExprDependence computeDependence(OpenACCAsteriskSizeExpr *E);

} // namespace clang
#endif
9 changes: 6 additions & 3 deletions clang/include/clang/AST/DeclCXX.h
Original file line number Diff line number Diff line change
Expand Up @@ -1965,9 +1965,11 @@ class CXXDeductionGuideDecl : public FunctionDecl {
ExplicitSpecifier ES,
const DeclarationNameInfo &NameInfo, QualType T,
TypeSourceInfo *TInfo, SourceLocation EndLocation,
CXXConstructorDecl *Ctor, DeductionCandidate Kind)
CXXConstructorDecl *Ctor, DeductionCandidate Kind,
Expr *TrailingRequiresClause)
: FunctionDecl(CXXDeductionGuide, C, DC, StartLoc, NameInfo, T, TInfo,
SC_None, false, false, ConstexprSpecKind::Unspecified),
SC_None, false, false, ConstexprSpecKind::Unspecified,
TrailingRequiresClause),
Ctor(Ctor), ExplicitSpec(ES) {
if (EndLocation.isValid())
setRangeEnd(EndLocation);
Expand All @@ -1987,7 +1989,8 @@ class CXXDeductionGuideDecl : public FunctionDecl {
ExplicitSpecifier ES, const DeclarationNameInfo &NameInfo, QualType T,
TypeSourceInfo *TInfo, SourceLocation EndLocation,
CXXConstructorDecl *Ctor = nullptr,
DeductionCandidate Kind = DeductionCandidate::Normal);
DeductionCandidate Kind = DeductionCandidate::Normal,
Expr *TrailingRequiresClause = nullptr);

static CXXDeductionGuideDecl *CreateDeserialized(ASTContext &C,
GlobalDeclID ID);
Expand Down
44 changes: 44 additions & 0 deletions clang/include/clang/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -2072,6 +2072,41 @@ class PredefinedExpr final
}
};

/// This expression type represents an asterisk in an OpenACC Size-Expr, used in
/// the 'tile' and 'gang' clauses. It is of 'int' type, but should not be
/// evaluated.
class OpenACCAsteriskSizeExpr final : public Expr {
friend class ASTStmtReader;
SourceLocation AsteriskLoc;

OpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc, QualType IntTy)
: Expr(OpenACCAsteriskSizeExprClass, IntTy, VK_PRValue, OK_Ordinary),
AsteriskLoc(AsteriskLoc) {}

void setAsteriskLocation(SourceLocation Loc) { AsteriskLoc = Loc; }

public:
static OpenACCAsteriskSizeExpr *Create(const ASTContext &C,
SourceLocation Loc);
static OpenACCAsteriskSizeExpr *CreateEmpty(const ASTContext &C);

SourceLocation getBeginLoc() const { return AsteriskLoc; }
SourceLocation getEndLoc() const { return AsteriskLoc; }
SourceLocation getLocation() const { return AsteriskLoc; }

static bool classof(const Stmt *T) {
return T->getStmtClass() == OpenACCAsteriskSizeExprClass;
}
// Iterators
child_range children() {
return child_range(child_iterator(), child_iterator());
}

const_child_range children() const {
return const_child_range(const_child_iterator(), const_child_iterator());
}
};

// This represents a use of the __builtin_sycl_unique_stable_name, which takes a
// type-id, and at CodeGen time emits a unique string representation of the
// type in a way that permits us to properly encode information about the SYCL
Expand Down Expand Up @@ -2135,11 +2170,13 @@ class SYCLUniqueStableNameExpr final : public Expr {
class ParenExpr : public Expr {
SourceLocation L, R;
Stmt *Val;

public:
ParenExpr(SourceLocation l, SourceLocation r, Expr *val)
: Expr(ParenExprClass, val->getType(), val->getValueKind(),
val->getObjectKind()),
L(l), R(r), Val(val) {
ParenExprBits.ProducedByFoldExpansion = false;
setDependence(computeDependence(this));
}

Expand Down Expand Up @@ -2171,6 +2208,13 @@ class ParenExpr : public Expr {
const_child_range children() const {
return const_child_range(&Val, &Val + 1);
}

bool isProducedByFoldExpansion() const {
return ParenExprBits.ProducedByFoldExpansion != 0;
}
void setIsProducedByFoldExpansion(bool ProducedByFoldExpansion = true) {
ParenExprBits.ProducedByFoldExpansion = ProducedByFoldExpansion;
}
};

/// UnaryOperator - This represents the unary-expression's (except sizeof and
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/AST/JSONNodeDumper.h
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ class JSONNodeDumper

void VisitDeclRefExpr(const DeclRefExpr *DRE);
void VisitSYCLUniqueStableNameExpr(const SYCLUniqueStableNameExpr *E);
void VisitOpenACCAsteriskSizeExpr(const OpenACCAsteriskSizeExpr *E);
void VisitPredefinedExpr(const PredefinedExpr *PE);
void VisitUnaryOperator(const UnaryOperator *UO);
void VisitBinaryOperator(const BinaryOperator *BO);
Expand Down
55 changes: 55 additions & 0 deletions clang/include/clang/AST/OpenACCClause.h
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,35 @@ class OpenACCNumGangsClause final
}
};

class OpenACCTileClause final
: public OpenACCClauseWithExprs,
public llvm::TrailingObjects<OpenACCTileClause, Expr *> {
OpenACCTileClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> SizeExprs, SourceLocation EndLoc)
: OpenACCClauseWithExprs(OpenACCClauseKind::Tile, BeginLoc, LParenLoc,
EndLoc) {
std::uninitialized_copy(SizeExprs.begin(), SizeExprs.end(),
getTrailingObjects<Expr *>());
setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), SizeExprs.size()));
}

public:
static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Tile;
}
static OpenACCTileClause *Create(const ASTContext &C, SourceLocation BeginLoc,
SourceLocation LParenLoc,
ArrayRef<Expr *> SizeExprs,
SourceLocation EndLoc);
llvm::ArrayRef<Expr *> getSizeExprs() {
return OpenACCClauseWithExprs::getExprs();
}

llvm::ArrayRef<Expr *> getSizeExprs() const {
return OpenACCClauseWithExprs::getExprs();
}
};

/// Represents one of a handful of clauses that have a single integer
/// expression.
class OpenACCClauseWithSingleIntExpr : public OpenACCClauseWithExprs {
Expand Down Expand Up @@ -547,6 +576,32 @@ class OpenACCAsyncClause : public OpenACCClauseWithSingleIntExpr {
SourceLocation EndLoc);
};

/// Represents a 'collapse' clause on a 'loop' construct. This clause takes an
/// integer constant expression 'N' that represents how deep to collapse the
/// construct. It also takes an optional 'force' tag that permits intervening
/// code in the loops.
class OpenACCCollapseClause : public OpenACCClauseWithSingleIntExpr {
bool HasForce = false;

OpenACCCollapseClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
bool HasForce, Expr *LoopCount, SourceLocation EndLoc);

public:
const Expr *getLoopCount() const { return getIntExpr(); }
Expr *getLoopCount() { return getIntExpr(); }

bool hasForce() const { return HasForce; }

static bool classof(const OpenACCClause *C) {
return C->getClauseKind() == OpenACCClauseKind::Collapse;
}

static OpenACCCollapseClause *Create(const ASTContext &C,
SourceLocation BeginLoc,
SourceLocation LParenLoc, bool HasForce,
Expr *LoopCount, SourceLocation EndLoc);
};

/// Represents a clause with one or more 'var' objects, represented as an expr,
/// as its arguments. Var-list is expected to be stored in trailing storage.
/// For now, we're just storing the original expression in its entirety, unlike
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/AST/RecursiveASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -2867,6 +2867,7 @@ DEF_TRAVERSE_STMT(ParenListExpr, {})
DEF_TRAVERSE_STMT(SYCLUniqueStableNameExpr, {
TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
})
DEF_TRAVERSE_STMT(OpenACCAsteriskSizeExpr, {})
DEF_TRAVERSE_STMT(PredefinedExpr, {})
DEF_TRAVERSE_STMT(ShuffleVectorExpr, {})
DEF_TRAVERSE_STMT(ConvertVectorExpr, {})
Expand Down
13 changes: 13 additions & 0 deletions clang/include/clang/AST/Stmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,18 @@ class alignas(void *) Stmt {
unsigned Kind : 3;
};

class ParenExprBitfields {
friend class ASTStmtReader;
friend class ASTStmtWriter;
friend class ParenExpr;

LLVM_PREFERRED_TYPE(ExprBitfields)
unsigned : NumExprBits;

LLVM_PREFERRED_TYPE(bool)
unsigned ProducedByFoldExpansion : 1;
};

class StmtExprBitfields {
friend class ASTStmtReader;
friend class StmtExpr;
Expand Down Expand Up @@ -1241,6 +1253,7 @@ class alignas(void *) Stmt {
GenericSelectionExprBitfields GenericSelectionExprBits;
PseudoObjectExprBitfields PseudoObjectExprBits;
SourceLocExprBitfields SourceLocExprBits;
ParenExprBitfields ParenExprBits;

// GNU Extensions.
StmtExprBitfields StmtExprBits;
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/AST/TextNodeDumper.h
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,7 @@ class TextNodeDumper
void VisitHLSLOutArgExpr(const HLSLOutArgExpr *E);
void VisitOpenACCConstructStmt(const OpenACCConstructStmt *S);
void VisitOpenACCLoopConstruct(const OpenACCLoopConstruct *S);
void VisitOpenACCAsteriskSizeExpr(const OpenACCAsteriskSizeExpr *S);
void VisitEmbedExpr(const EmbedExpr *S);
void VisitAtomicExpr(const AtomicExpr *AE);
};
Expand Down
134 changes: 113 additions & 21 deletions clang/include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#include "llvm/Support/PointerLikeTypeTraits.h"
#include "llvm/Support/TrailingObjects.h"
#include "llvm/Support/type_traits.h"
#include <bitset>
#include <cassert>
#include <cstddef>
#include <cstdint>
Expand Down Expand Up @@ -119,6 +120,8 @@ class EnumDecl;
class Expr;
class ExtQualsTypeCommonBase;
class FunctionDecl;
class FunctionEffectsRef;
class FunctionEffectKindSet;
class FunctionEffectSet;
class IdentifierInfo;
class NamedDecl;
Expand Down Expand Up @@ -3050,7 +3053,7 @@ class BuiltinType : public Type {
#define WASM_TYPE(Name, Id, SingletonId) Id,
#include "clang/Basic/WebAssemblyReferenceTypes.def"
// AMDGPU types
#define AMDGPU_TYPE(Name, Id, SingletonId) Id,
#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) Id,
#include "clang/Basic/AMDGPUTypes.def"
// HLSL intangible Types
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) Id,
Expand Down Expand Up @@ -4712,12 +4715,13 @@ class FunctionEffect {
public:
/// Identifies the particular effect.
enum class Kind : uint8_t {
None = 0,
NonBlocking = 1,
NonAllocating = 2,
Blocking = 3,
Allocating = 4
NonBlocking,
NonAllocating,
Blocking,
Allocating,
Last = Allocating
};
constexpr static size_t KindCount = static_cast<size_t>(Kind::Last) + 1;

/// Flags describing some behaviors of the effect.
using Flags = unsigned;
Expand All @@ -4743,8 +4747,6 @@ class FunctionEffect {
// be considered for uniqueness.

public:
FunctionEffect() : FKind(Kind::None) {}

explicit FunctionEffect(Kind K) : FKind(K) {}

/// The kind of the effect.
Expand Down Expand Up @@ -4773,35 +4775,43 @@ class FunctionEffect {
case Kind::Blocking:
case Kind::Allocating:
return 0;
case Kind::None:
break;
}
llvm_unreachable("unknown effect kind");
}

/// The description printed in diagnostics, e.g. 'nonblocking'.
StringRef name() const;

/// Return true if the effect is allowed to be inferred on the callee,
/// which is either a FunctionDecl or BlockDecl.
friend raw_ostream &operator<<(raw_ostream &OS,
const FunctionEffect &Effect) {
OS << Effect.name();
return OS;
}

/// Determine whether the effect is allowed to be inferred on the callee,
/// which is either a FunctionDecl or BlockDecl. If the returned optional
/// is empty, inference is permitted; otherwise it holds the effect which
/// blocked inference.
/// Example: This allows nonblocking(false) to prevent inference for the
/// function.
bool canInferOnFunction(const Decl &Callee) const;
std::optional<FunctionEffect>
effectProhibitingInference(const Decl &Callee,
FunctionEffectKindSet CalleeFX) const;

// Return false for success. When true is returned for a direct call, then the
// FE_InferrableOnCallees flag may trigger inference rather than an immediate
// diagnostic. Caller should be assumed to have the effect (it may not have it
// explicitly when inferring).
bool shouldDiagnoseFunctionCall(bool Direct,
ArrayRef<FunctionEffect> CalleeFX) const;
FunctionEffectKindSet CalleeFX) const;

friend bool operator==(const FunctionEffect &LHS, const FunctionEffect &RHS) {
friend bool operator==(FunctionEffect LHS, FunctionEffect RHS) {
return LHS.FKind == RHS.FKind;
}
friend bool operator!=(const FunctionEffect &LHS, const FunctionEffect &RHS) {
friend bool operator!=(FunctionEffect LHS, FunctionEffect RHS) {
return !(LHS == RHS);
}
friend bool operator<(const FunctionEffect &LHS, const FunctionEffect &RHS) {
friend bool operator<(FunctionEffect LHS, FunctionEffect RHS) {
return LHS.FKind < RHS.FKind;
}
};
Expand Down Expand Up @@ -4829,13 +4839,14 @@ struct FunctionEffectWithCondition {
FunctionEffect Effect;
EffectConditionExpr Cond;

FunctionEffectWithCondition() = default;
FunctionEffectWithCondition(const FunctionEffect &E,
const EffectConditionExpr &C)
FunctionEffectWithCondition(FunctionEffect E, const EffectConditionExpr &C)
: Effect(E), Cond(C) {}

/// Return a textual description of the effect, and its condition, if any.
std::string description() const;

friend raw_ostream &operator<<(raw_ostream &OS,
const FunctionEffectWithCondition &CFE);
};

/// Support iteration in parallel through a pair of FunctionEffect and
Expand Down Expand Up @@ -4940,6 +4951,85 @@ class FunctionEffectsRef {
void dump(llvm::raw_ostream &OS) const;
};

/// A mutable set of FunctionEffect::Kind.
class FunctionEffectKindSet {
// For now this only needs to be a bitmap.
constexpr static size_t EndBitPos = FunctionEffect::KindCount;
using KindBitsT = std::bitset<EndBitPos>;

KindBitsT KindBits{};

explicit FunctionEffectKindSet(KindBitsT KB) : KindBits(KB) {}

// Functions to translate between an effect kind, starting at 1, and a
// position in the bitset.

constexpr static size_t kindToPos(FunctionEffect::Kind K) {
return static_cast<size_t>(K);
}

constexpr static FunctionEffect::Kind posToKind(size_t Pos) {
return static_cast<FunctionEffect::Kind>(Pos);
}

// Iterates through the bits which are set.
class iterator {
const FunctionEffectKindSet *Outer = nullptr;
size_t Idx = 0;

// If Idx does not reference a set bit, advance it until it does,
// or until it reaches EndBitPos.
void advanceToNextSetBit() {
while (Idx < EndBitPos && !Outer->KindBits.test(Idx))
++Idx;
}

public:
iterator();
iterator(const FunctionEffectKindSet &O, size_t I) : Outer(&O), Idx(I) {
advanceToNextSetBit();
}
bool operator==(const iterator &Other) const { return Idx == Other.Idx; }
bool operator!=(const iterator &Other) const { return Idx != Other.Idx; }

iterator operator++() {
++Idx;
advanceToNextSetBit();
return *this;
}

FunctionEffect operator*() const {
assert(Idx < EndBitPos && "Dereference of end iterator");
return FunctionEffect(posToKind(Idx));
}
};

public:
FunctionEffectKindSet() = default;
explicit FunctionEffectKindSet(FunctionEffectsRef FX) { insert(FX); }

iterator begin() const { return iterator(*this, 0); }
iterator end() const { return iterator(*this, EndBitPos); }

void insert(FunctionEffect Effect) { KindBits.set(kindToPos(Effect.kind())); }
void insert(FunctionEffectsRef FX) {
for (FunctionEffect Item : FX.effects())
insert(Item);
}
void insert(FunctionEffectKindSet Set) { KindBits |= Set.KindBits; }

bool empty() const { return KindBits.none(); }
bool contains(const FunctionEffect::Kind EK) const {
return KindBits.test(kindToPos(EK));
}
void dump(llvm::raw_ostream &OS) const;

static FunctionEffectKindSet difference(FunctionEffectKindSet LHS,
FunctionEffectKindSet RHS) {
return FunctionEffectKindSet(LHS.KindBits & ~RHS.KindBits);
}
};

/// A mutable set of FunctionEffects and possibly conditions attached to them.
/// Used to compare and merge effects on declarations.
///
Expand Down Expand Up @@ -6191,7 +6281,9 @@ class HLSLAttributedResourceType : public Type, public llvm::FoldingSetNode {

HLSLAttributedResourceType(QualType Canon, QualType Wrapped,
QualType Contained, const Attributes &Attrs)
: Type(HLSLAttributedResource, Canon, Wrapped->getDependence()),
: Type(HLSLAttributedResource, Canon,
Contained.isNull() ? TypeDependence::None
: Contained->getDependence()),
WrappedType(Wrapped), ContainedType(Contained), Attrs(Attrs) {}

public:
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/AST/TypeProperties.td
Original file line number Diff line number Diff line change
Expand Up @@ -893,7 +893,7 @@ let Class = BuiltinType in {
case BuiltinType::ID: return ctx.SINGLETON_ID;
#include "clang/Basic/WebAssemblyReferenceTypes.def"

#define AMDGPU_TYPE(NAME, ID, SINGLETON_ID) \
#define AMDGPU_TYPE(NAME, ID, SINGLETON_ID, WIDTH, ALIGN) \
case BuiltinType::ID: return ctx.SINGLETON_ID;
#include "clang/Basic/AMDGPUTypes.def"

Expand Down
6 changes: 3 additions & 3 deletions clang/include/clang/Basic/AMDGPUTypes.def
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
//===----------------------------------------------------------------------===//

#ifndef AMDGPU_OPAQUE_PTR_TYPE
#define AMDGPU_OPAQUE_PTR_TYPE(Name, AS, Width, Align, Id, SingletonId) \
AMDGPU_TYPE(Name, Id, SingletonId)
#define AMDGPU_OPAQUE_PTR_TYPE(Name, Id, SingletonId, Width, Align, AS) \
AMDGPU_TYPE(Name, Id, SingletonId, Width, Align)
#endif

AMDGPU_OPAQUE_PTR_TYPE("__amdgpu_buffer_rsrc_t", 8, 128, 128, AMDGPUBufferRsrc, AMDGPUBufferRsrcTy)
AMDGPU_OPAQUE_PTR_TYPE("__amdgpu_buffer_rsrc_t", AMDGPUBufferRsrc, AMDGPUBufferRsrcTy, 128, 128, 8)

#undef AMDGPU_TYPE
#undef AMDGPU_OPAQUE_PTR_TYPE
4 changes: 2 additions & 2 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -8482,9 +8482,9 @@ compiler warnings:
- A redeclaration of a ``nonblocking`` or ``nonallocating`` function must also be declared with
the same attribute (or a stronger one). A redeclaration may add an attribute.

The warnings are controlled by ``-Wfunction-effects``, which is enabled by default.
The warnings are controlled by ``-Wfunction-effects``, which is disabled by default.

In a future commit, the compiler will diagnose function calls from ``nonblocking`` and ``nonallocating``
The compiler also diagnoses function calls from ``nonblocking`` and ``nonallocating``
functions to other functions which lack the appropriate attribute.
}];
}
Expand Down
42 changes: 42 additions & 0 deletions clang/include/clang/Basic/Builtins.td
Original file line number Diff line number Diff line change
Expand Up @@ -1250,6 +1250,12 @@ def ElementwiseATan : Builtin {
let Prototype = "void(...)";
}

def ElementwiseATan2 : Builtin {
let Spellings = ["__builtin_elementwise_atan2"];
let Attributes = [NoThrow, Const, CustomTypeChecking];
let Prototype = "void(...)";
}

def ElementwiseBitreverse : Builtin {
let Spellings = ["__builtin_elementwise_bitreverse"];
let Attributes = [NoThrow, Const, CustomTypeChecking];
Expand All @@ -1268,6 +1274,18 @@ def ElementwiseMin : Builtin {
let Prototype = "void(...)";
}

def ElementwiseMaximum : Builtin {
let Spellings = ["__builtin_elementwise_maximum"];
let Attributes = [NoThrow, Const, CustomTypeChecking];
let Prototype = "void(...)";
}

def ElementwiseMinimum : Builtin {
let Spellings = ["__builtin_elementwise_minimum"];
let Attributes = [NoThrow, Const, CustomTypeChecking];
let Prototype = "void(...)";
}

def ElementwiseCeil : Builtin {
let Spellings = ["__builtin_elementwise_ceil"];
let Attributes = [NoThrow, Const, CustomTypeChecking];
Expand Down Expand Up @@ -1442,6 +1460,18 @@ def ReduceMin : Builtin {
let Prototype = "void(...)";
}

def ReduceMaximum : Builtin {
let Spellings = ["__builtin_reduce_maximum"];
let Attributes = [NoThrow, Const, CustomTypeChecking];
let Prototype = "void(...)";
}

def ReduceMinimum : Builtin {
let Spellings = ["__builtin_reduce_minimum"];
let Attributes = [NoThrow, Const, CustomTypeChecking];
let Prototype = "void(...)";
}

def ReduceXor : Builtin {
let Spellings = ["__builtin_reduce_xor"];
let Attributes = [NoThrow, Const, CustomTypeChecking];
Expand Down Expand Up @@ -4709,6 +4739,12 @@ def HLSLClamp : LangBuiltin<"HLSL_LANG"> {
let Prototype = "void(...)";
}

def HLSLCross: LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_cross"];
let Attributes = [NoThrow, Const];
let Prototype = "void(...)";
}

def HLSLDotProduct : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_dot"];
let Attributes = [NoThrow, Const];
Expand Down Expand Up @@ -4788,6 +4824,12 @@ def HLSLStep: LangBuiltin<"HLSL_LANG"> {
let Prototype = "void(...)";
}

def HLSLRadians : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_elementwise_radians"];
let Attributes = [NoThrow, Const];
let Prototype = "void(...)";
}

// Builtins for XRay.
def XRayCustomEvent : Builtin {
let Spellings = ["__xray_customevent"];
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Basic/BuiltinsRISCV.td
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,8 @@ let Features = "zihintntl", Attributes = [CustomTypeChecking] in {
def ntl_load : RISCVBuiltin<"void(...)">;
def ntl_store : RISCVBuiltin<"void(...)">;
} // Features = "zihintntl", Attributes = [CustomTypeChecking]

//===----------------------------------------------------------------------===//
// XCV extensions.
//===----------------------------------------------------------------------===//
include "clang/Basic/BuiltinsRISCVXCV.td"
41 changes: 41 additions & 0 deletions clang/include/clang/Basic/BuiltinsRISCVXCV.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//==- BuiltinsRISCVXCV.td - RISC-V CORE-V Builtin database ----*- 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
//
//===----------------------------------------------------------------------===//
//
// This file defines the CORE-V-specific builtin function database. Users of
// this file must define the BUILTIN macro to make use of this information.
//
//===----------------------------------------------------------------------===//

class RISCXCVBuiltin<string prototype, string features = ""> : TargetBuiltin {
let Spellings = ["__builtin_riscv_cv_" # NAME];
let Prototype = prototype;
let Features = features;
}

let Attributes = [NoThrow, Const] in {
//===----------------------------------------------------------------------===//
// XCValu extension.
//===----------------------------------------------------------------------===//
def alu_slet : RISCXCVBuiltin<"int(int, int)", "xcvalu">;
def alu_sletu : RISCXCVBuiltin<"int(unsigned int, unsigned int)", "xcvalu">;
def alu_exths : RISCXCVBuiltin<"int(int)", "xcvalu">;
def alu_exthz : RISCXCVBuiltin<"unsigned int(unsigned int)", "xcvalu">;
def alu_extbs : RISCXCVBuiltin<"int(int)", "xcvalu">;
def alu_extbz : RISCXCVBuiltin<"unsigned int(unsigned int)", "xcvalu">;

def alu_clip : RISCXCVBuiltin<"int(int, int)", "xcvalu">;
def alu_clipu : RISCXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvalu">;
def alu_addN : RISCXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
def alu_adduN : RISCXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
def alu_addRN : RISCXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
def alu_adduRN : RISCXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
def alu_subN : RISCXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
def alu_subuN : RISCXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
def alu_subRN : RISCXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
def alu_subuRN : RISCXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
} // Attributes = [NoThrow, Const]
18 changes: 9 additions & 9 deletions clang/include/clang/Basic/BuiltinsX86.def
Original file line number Diff line number Diff line change
Expand Up @@ -543,26 +543,26 @@ TARGET_BUILTIN(__builtin_ia32_wbinvd, "v", "n", "")
TARGET_BUILTIN(__builtin_ia32_wbnoinvd, "v", "n", "wbnoinvd")

// ADX
TARGET_BUILTIN(__builtin_ia32_addcarryx_u32, "UcUcUiUiUi*", "n", "")
TARGET_BUILTIN(__builtin_ia32_subborrow_u32, "UcUcUiUiUi*", "n", "")
TARGET_BUILTIN(__builtin_ia32_addcarryx_u32, "UcUcUiUiUi*", "nE", "")
TARGET_BUILTIN(__builtin_ia32_subborrow_u32, "UcUcUiUiUi*", "nE", "")

// RDSEED
TARGET_BUILTIN(__builtin_ia32_rdseed16_step, "UiUs*", "n", "rdseed")
TARGET_BUILTIN(__builtin_ia32_rdseed32_step, "UiUi*", "n", "rdseed")

// LZCNT
TARGET_BUILTIN(__builtin_ia32_lzcnt_u16, "UsUs", "nc", "lzcnt")
TARGET_BUILTIN(__builtin_ia32_lzcnt_u32, "UiUi", "nc", "lzcnt")
TARGET_BUILTIN(__builtin_ia32_lzcnt_u16, "UsUs", "ncE", "lzcnt")
TARGET_BUILTIN(__builtin_ia32_lzcnt_u32, "UiUi", "ncE", "lzcnt")

// BMI
TARGET_BUILTIN(__builtin_ia32_bextr_u32, "UiUiUi", "ncE", "bmi")
TARGET_BUILTIN(__builtin_ia32_tzcnt_u16, "UsUs", "nc", "")
TARGET_BUILTIN(__builtin_ia32_tzcnt_u32, "UiUi", "nc", "")
TARGET_BUILTIN(__builtin_ia32_tzcnt_u16, "UsUs", "ncE", "")
TARGET_BUILTIN(__builtin_ia32_tzcnt_u32, "UiUi", "ncE", "")

// BMI2
TARGET_BUILTIN(__builtin_ia32_bzhi_si, "UiUiUi", "nc", "bmi2")
TARGET_BUILTIN(__builtin_ia32_pdep_si, "UiUiUi", "nc", "bmi2")
TARGET_BUILTIN(__builtin_ia32_pext_si, "UiUiUi", "nc", "bmi2")
TARGET_BUILTIN(__builtin_ia32_bzhi_si, "UiUiUi", "ncE", "bmi2")
TARGET_BUILTIN(__builtin_ia32_pdep_si, "UiUiUi", "ncE", "bmi2")
TARGET_BUILTIN(__builtin_ia32_pext_si, "UiUiUi", "ncE", "bmi2")

// TBM
TARGET_BUILTIN(__builtin_ia32_bextri_u32, "UiUiIUi", "ncE", "tbm")
Expand Down
14 changes: 7 additions & 7 deletions clang/include/clang/Basic/BuiltinsX86_64.def
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,16 @@ TARGET_BUILTIN(__builtin_ia32_incsspq, "vUOi", "n", "shstk")
TARGET_BUILTIN(__builtin_ia32_rdsspq, "UOiUOi", "n", "shstk")
TARGET_BUILTIN(__builtin_ia32_wrssq, "vUOiv*", "n", "shstk")
TARGET_BUILTIN(__builtin_ia32_wrussq, "vUOiv*", "n", "shstk")
TARGET_BUILTIN(__builtin_ia32_addcarryx_u64, "UcUcUOiUOiUOi*", "n", "")
TARGET_BUILTIN(__builtin_ia32_subborrow_u64, "UcUcUOiUOiUOi*", "n", "")
TARGET_BUILTIN(__builtin_ia32_addcarryx_u64, "UcUcUOiUOiUOi*", "nE", "")
TARGET_BUILTIN(__builtin_ia32_subborrow_u64, "UcUcUOiUOiUOi*", "nE", "")
TARGET_BUILTIN(__builtin_ia32_rdrand64_step, "UiUOi*", "n", "rdrnd")
TARGET_BUILTIN(__builtin_ia32_rdseed64_step, "UiUOi*", "n", "rdseed")
TARGET_BUILTIN(__builtin_ia32_lzcnt_u64, "UOiUOi", "nc", "lzcnt")
TARGET_BUILTIN(__builtin_ia32_lzcnt_u64, "UOiUOi", "ncE", "lzcnt")
TARGET_BUILTIN(__builtin_ia32_bextr_u64, "UOiUOiUOi", "ncE", "bmi")
TARGET_BUILTIN(__builtin_ia32_tzcnt_u64, "UOiUOi", "nc", "")
TARGET_BUILTIN(__builtin_ia32_bzhi_di, "UOiUOiUOi", "nc", "bmi2")
TARGET_BUILTIN(__builtin_ia32_pdep_di, "UOiUOiUOi", "nc", "bmi2")
TARGET_BUILTIN(__builtin_ia32_pext_di, "UOiUOiUOi", "nc", "bmi2")
TARGET_BUILTIN(__builtin_ia32_tzcnt_u64, "UOiUOi", "ncE", "")
TARGET_BUILTIN(__builtin_ia32_bzhi_di, "UOiUOiUOi", "ncE", "bmi2")
TARGET_BUILTIN(__builtin_ia32_pdep_di, "UOiUOiUOi", "ncE", "bmi2")
TARGET_BUILTIN(__builtin_ia32_pext_di, "UOiUOiUOi", "ncE", "bmi2")
TARGET_BUILTIN(__builtin_ia32_bextri_u64, "UOiUOiIUOi", "ncE", "tbm")
TARGET_BUILTIN(__builtin_ia32_lwpins64, "UcUOiUiIUi", "n", "lwp")
TARGET_BUILTIN(__builtin_ia32_lwpval64, "vUOiUiIUi", "n", "lwp")
Expand Down
11 changes: 6 additions & 5 deletions clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -1125,6 +1125,11 @@ def ThreadSafety : DiagGroup<"thread-safety",
def ThreadSafetyVerbose : DiagGroup<"thread-safety-verbose">;
def ThreadSafetyBeta : DiagGroup<"thread-safety-beta">;

// Warnings and notes related to the function effects system which underlies
// the nonblocking and nonallocating attributes.
def FunctionEffects : DiagGroup<"function-effects">;
def PerfConstraintImpliesNoexcept : DiagGroup<"perf-constraint-implies-noexcept">;

// Uniqueness Analysis warnings
def Consumed : DiagGroup<"consumed">;

Expand All @@ -1133,7 +1138,7 @@ def Consumed : DiagGroup<"consumed">;
// DefaultIgnore in addition to putting it here.
def All : DiagGroup<"all", [Most, Parentheses, Switch, SwitchBool,
MisleadingIndentation, PackedNonPod,
VLACxxExtension]>;
VLACxxExtension, PerfConstraintImpliesNoexcept]>;

// Warnings that should be in clang-cl /w4.
def : DiagGroup<"CL4", [All, Extra]>;
Expand Down Expand Up @@ -1566,10 +1571,6 @@ def UnsafeBufferUsageInContainer : DiagGroup<"unsafe-buffer-usage-in-container">
def UnsafeBufferUsageInLibcCall : DiagGroup<"unsafe-buffer-usage-in-libc-call">;
def UnsafeBufferUsage : DiagGroup<"unsafe-buffer-usage", [UnsafeBufferUsageInContainer, UnsafeBufferUsageInLibcCall]>;

// Warnings and notes related to the function effects system underlying
// the nonblocking and nonallocating attributes.
def FunctionEffects : DiagGroup<"function-effects">;

// Warnings and notes InstallAPI verification.
def InstallAPIViolation : DiagGroup<"installapi-violation">;

Expand Down
94 changes: 85 additions & 9 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -3050,8 +3050,6 @@ def note_is_deducible_constraint_evaluated_to_false : Note<
"cannot deduce template arguments for %0 from %1">;
def err_constrained_virtual_method : Error<
"virtual function cannot have a requires clause">;
def err_trailing_requires_clause_on_deduction_guide : Error<
"deduction guide cannot have a requires clause">;
def err_constrained_non_templated_function
: Error<"non-templated function cannot have a requires clause">;
def err_non_temp_spec_requires_clause : Error<
Expand Down Expand Up @@ -5264,6 +5262,13 @@ def note_template_arg_refers_here_func : Note<
def err_template_arg_template_params_mismatch : Error<
"template template argument has different template parameters than its "
"corresponding template template parameter">;
def note_template_arg_template_params_mismatch : Note<
"template template argument has different template parameters than its "
"corresponding template template parameter">;
def err_non_deduced_mismatch : Error<
"could not match %diff{$ against $|types}0,1">;
def err_inconsistent_deduction : Error<
"conflicting deduction %diff{$ against $|types}0,1 for parameter">;
def err_template_arg_not_integral_or_enumeral : Error<
"non-type template argument of type %0 must have an integral or enumeration"
" type">;
Expand Down Expand Up @@ -10505,8 +10510,8 @@ def err_first_argument_to_cwsc_pdtor_call : Error<
def err_second_argument_to_cwsc_not_pointer : Error<
"second argument to __builtin_call_with_static_chain must be of pointer type">;

def err_vector_incorrect_num_initializers : Error<
"%select{too many|too few}0 elements in vector initialization (expected %1 elements, have %2)">;
def err_vector_incorrect_num_elements : Error<
"%select{too many|too few}0 elements in vector %select{initialization|operand}3 (expected %1 elements, have %2)">;
def err_altivec_empty_initializer : Error<"expected initializer">;

def err_invalid_neon_type_code : Error<
Expand Down Expand Up @@ -10967,19 +10972,68 @@ def warn_imp_cast_drops_unaligned : Warning<
InGroup<DiagGroup<"unaligned-qualifier-implicit-cast">>;

// Function effects
def warn_func_effect_violation : Warning<
"%select{function|constructor|destructor|lambda|block|member initializer of constructor}0 "
"with '%1' attribute "
"must not %select{allocate or deallocate memory|throw or catch exceptions|"
"have static local variables|use thread-local variables|access ObjC methods or properties}2">,
InGroup<FunctionEffects>, DefaultIgnore;
def note_func_effect_violation : Note<
"%select{function|constructor|destructor|lambda|block|member initializer}0 "
"cannot be inferred '%1' because it "
"%select{allocates or deallocates memory|throws or catches exceptions|"
"has a static local variable|uses a thread-local variable|"
"accesses an ObjC method or property}2">;
def warn_func_effect_calls_func_without_effect : Warning<
"%select{function|constructor|destructor|lambda|block|member initializer of constructor}0 "
"with '%1' attribute "
"must not call non-'%1' "
"%select{function|constructor|destructor|lambda|block}2 "
"'%3'">,
InGroup<FunctionEffects>, DefaultIgnore;
def note_func_effect_calls_func_without_effect : Note<
"%select{function|constructor|destructor|lambda|block|member initializer}0 "
"cannot be inferred '%1' because it calls non-'%1' "
"%select{function|constructor|destructor|lambda|block}2 "
"'%3'">;
def warn_func_effect_calls_expr_without_effect : Warning<
"%select{function|constructor|destructor|lambda|block|member initializer of constructor}0 "
"with '%1' attribute "
"must not call non-'%1' expression">,
InGroup<FunctionEffects>, DefaultIgnore;
def note_func_effect_call_extern : Note<
"declaration cannot be inferred '%0' because it has no definition in this translation unit">;
def note_func_effect_call_disallows_inference : Note<
"%select{function|constructor|destructor|lambda|block}0 "
"does not permit inference of '%1' because it is declared '%2'">;
def note_func_effect_call_indirect : Note<
"%select{virtual method|function pointer}0 cannot be inferred '%1'">;
def warn_perf_constraint_implies_noexcept : Warning<
"%select{function|constructor|destructor|lambda|block}0 "
"with '%1' attribute should be declared noexcept">,
InGroup<PerfConstraintImpliesNoexcept>, DefaultIgnore;

// FIXME: It would be nice if we could provide fuller template expansion notes.
def note_func_effect_from_template : Note<
"in template expansion here">;
def note_func_effect_in_constructor : Note<
"in%select{| implicit}0 constructor here">;
def note_in_evaluating_default_argument : Note<
"in evaluating default argument here">;

// spoofing nonblocking/nonallocating
def warn_invalid_add_func_effects : Warning<
"attribute '%0' should not be added via type conversion">,
InGroup<FunctionEffects>;
InGroup<FunctionEffects>, DefaultIgnore;
def warn_mismatched_func_effect_override : Warning<
"attribute '%0' on overriding function does not match base declaration">,
InGroup<FunctionEffects>;
InGroup<FunctionEffects>, DefaultIgnore;
def warn_mismatched_func_effect_redeclaration : Warning<
"attribute '%0' on function does not match previous declaration">,
InGroup<FunctionEffects>;
InGroup<FunctionEffects>, DefaultIgnore;
def warn_conflicting_func_effects : Warning<
"effects conflict when merging declarations; kept '%0', discarded '%1'">,
InGroup<FunctionEffects>;
InGroup<FunctionEffects>, DefaultIgnore;
def err_func_with_effects_no_prototype : Error<
"'%0' function must have a prototype">;

Expand Down Expand Up @@ -12216,7 +12270,8 @@ def err_builtin_invalid_arg_type: Error <
"a floating point type|"
"a vector of integers|"
"an unsigned integer|"
"an 'int'}1 (was %2)">;
"an 'int'|"
"a vector of floating points}1 (was %2)">;

def err_builtin_matrix_disabled: Error<
"matrix types extension is disabled. Pass -fenable-matrix to enable it">;
Expand Down Expand Up @@ -12608,6 +12663,27 @@ def note_acc_construct_here : Note<"'%0' construct is here">;
def err_acc_loop_spec_conflict
: Error<"OpenACC clause '%0' on '%1' construct conflicts with previous "
"data dependence clause">;
def err_acc_collapse_loop_count
: Error<"OpenACC 'collapse' clause loop count must be a %select{constant "
"expression|positive integer value, evaluated to %1}0">;
def err_acc_size_expr_value
: Error<
"OpenACC 'tile' clause size expression must be %select{an asterisk "
"or a constant expression|positive integer value, evaluated to %1}0">;
def err_acc_invalid_in_loop
: Error<"%select{OpenACC '%2' construct|while loop|do loop}0 cannot appear "
"in intervening code of a 'loop' with a '%1' clause">;
def note_acc_active_clause_here
: Note<"active '%0' clause defined here">;
def err_acc_clause_multiple_loops
: Error<"more than one for-loop in a loop associated with OpenACC 'loop' "
"construct with a '%select{collapse|tile}0' clause">;
def err_acc_insufficient_loops
: Error<"'%0' clause specifies a loop count greater than the number "
"of available loops">;
def err_acc_intervening_code
: Error<"inner loops must be tightly nested inside a '%0' clause on "
"a 'loop' construct">;

// AMDGCN builtins diagnostics
def err_amdgcn_global_load_lds_size_invalid_value : Error<"invalid size value">;
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Basic/DiagnosticSerializationKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ def note_pch_vfsoverlay_files : Note<"%select{PCH|current translation unit}0 has
def note_pch_vfsoverlay_empty : Note<"%select{PCH|current translation unit}0 has no VFS overlays">;

def err_ast_file_version_too_old : Error<
"%select{PCH|module|AST}0 file '%1' uses an older PCH format that is no longer supported">;
"%select{PCH|module|AST}0 file '%1' uses an older format that is no longer supported">;
def err_ast_file_version_too_new : Error<
"%select{PCH|module|AST}0 file '%1' uses a newer PCH format that cannot be read">;
"%select{PCH|module|AST}0 file '%1' uses a newer format that cannot be read">;
def err_ast_file_different_branch : Error<
"%select{PCH|module|AST}0 file '%1' built from a different branch (%2) than the compiler (%3)">;
def err_ast_file_with_compiler_errors : Error<
Expand Down
4 changes: 3 additions & 1 deletion clang/include/clang/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,10 @@ class LangOptionsBase {

/// Attempt to be ABI-compatible with code generated by Clang 19.0.x.
/// This causes clang to:
/// - Incorrectly mangles the 'base type' substitutions of the CXX
/// - Incorrectly mangle the 'base type' substitutions of the CXX
/// construction vtable because it hasn't added 'type' as a substitution.
/// - Skip mangling enclosing class templates of member-like friend
/// function templates.
Ver19,

/// Conform to the underlying platform's C and C++ ABIs as closely
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/OpenACCClauses.def
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
VISIT_CLAUSE(Auto)
VISIT_CLAUSE(Async)
VISIT_CLAUSE(Attach)
VISIT_CLAUSE(Collapse)
VISIT_CLAUSE(Copy)
CLAUSE_ALIAS(PCopy, Copy, true)
CLAUSE_ALIAS(PresentOrCopy, Copy, true)
Expand Down Expand Up @@ -51,6 +52,7 @@ VISIT_CLAUSE(Private)
VISIT_CLAUSE(Reduction)
VISIT_CLAUSE(Self)
VISIT_CLAUSE(Seq)
VISIT_CLAUSE(Tile)
VISIT_CLAUSE(VectorLength)
VISIT_CLAUSE(Wait)

Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/StmtNodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -308,5 +308,8 @@ def OpenACCAssociatedStmtConstruct
def OpenACCComputeConstruct : StmtNode<OpenACCAssociatedStmtConstruct>;
def OpenACCLoopConstruct : StmtNode<OpenACCAssociatedStmtConstruct>;

// OpenACC Additional Expressions.
def OpenACCAsteriskSizeExpr : StmtNode<Expr>;

// HLSL Constructs.
def HLSLOutArgExpr : StmtNode<Expr>;
7 changes: 7 additions & 0 deletions clang/include/clang/Basic/arm_sme.td
Original file line number Diff line number Diff line change
Expand Up @@ -817,4 +817,11 @@ multiclass ZAReadzArray<string vg_num>{

defm SVREADZ_VG2 : ZAReadzArray<"2">;
defm SVREADZ_VG4 : ZAReadzArray<"4">;

let SMETargetGuard = "sme-lutv2" in {
def SVWRITE_LANE_ZT : SInst<"svwrite_lane_zt[_{d}]", "vidi", "cUcsUsiUilUlfhdb", MergeNone, "aarch64_sme_write_lane_zt", [IsStreaming, IsInOutZT0], [ImmCheck<0, ImmCheck0_0>, ImmCheck<2, ImmCheck1_3>]>;
def SVWRITE_ZT : SInst<"svwrite_zt[_{d}]", "vid", "cUcsUsiUilUlfhdb", MergeNone, "aarch64_sme_write_zt", [IsStreaming, IsOutZT0], [ImmCheck<0, ImmCheck0_0>]>;
def SVLUTI4_ZT_X4 : SInst<"svluti4_zt_{d}_x4", "4i2.u", "cUc", MergeNone, "aarch64_sme_luti4_zt_x4", [IsStreaming, IsInZT0], [ImmCheck<0, ImmCheck0_0>]>;
}

} // let SVETargetGuard = InvalidMode
Loading