407 changes: 365 additions & 42 deletions bolt/lib/Rewrite/LinuxKernelRewriter.cpp

Large diffs are not rendered by default.

54 changes: 43 additions & 11 deletions bolt/test/X86/linux-orc.s
Original file line number Diff line number Diff line change
@@ -1,28 +1,54 @@
# REQUIRES: system-linux

## Check that BOLT correctly reads ORC unwind information used by Linux kernel.
## Check that BOLT correctly updates ORC unwind information used by the Linux
## kernel.

# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o
# RUN: %clang %cflags -nostdlib %t.o -o %t.exe -Wl,--image-base=0xffffffff80000000,--no-dynamic-linker,--no-eh-frame-hdr
# RUN: %clang %cflags -nostdlib %t.o -o %t.exe \
# RUN: -Wl,--image-base=0xffffffff80000000,--no-dynamic-linker,--no-eh-frame-hdr

## Verify reading contents of ORC sections.

# RUN: llvm-bolt %t.exe --dump-orc -o /dev/null |& FileCheck %s \
# RUN: --check-prefix=CHECK-ORC

# CHECK-ORC: BOLT-INFO: ORC unwind information:
# CHECK-ORC-NEXT: {sp: 8, bp: 0, info: 0x5}: _start
# CHECK-ORC-NEXT: {terminator}
# CHECK-ORC-NEXT: {sp: 8, bp: 0, info: 0x5}: foo
# CHECK-ORC-NEXT: {sp: 16, bp: -16, info: 0x15}: foo
# CHECK-ORC-NEXT: {sp: 16, bp: -16, info: 0x14}: foo
# CHECK-ORC-NEXT: {sp: 8, bp: 0, info: 0x5}: foo
# CHECK-ORC-NEXT: {terminator}
# CHECK-ORC-NEXT: {terminator}
# CHECK-ORC-NEXT: {terminator}


## Verify ORC bindings to instructions.

# RUN: llvm-bolt %t.exe --print-normalized --dump-orc --print-orc -o %t.out \
# RUN: --bolt-info=0 |& FileCheck %s


## Verify ORC bindings after rewrite.

# RUN: llvm-bolt %t.out -o %t.out.1 --print-normalized --print-orc \
# RUN: |& FileCheck %s

## Verify ORC binding after rewrite when some of the functions are skipped.

# RUN: llvm-bolt %t.exe -o %t.out --skip-funcs=bar --bolt-info=0
# RUN: llvm-bolt %t.out -o %t.out.1 --print-normalized --print-orc \
# RUN: |& FileCheck %s

# CHECK: BOLT-INFO: Linux kernel binary detected
# CHECK: BOLT-INFO: ORC unwind information:
# CHECK-NEXT: {sp: 8, bp: 0, info: 0x5}: _start
# CHECK-NEXT: {sp: 0, bp: 0, info: 0x0}: _start
# CHECK-NEXT: {sp: 8, bp: 0, info: 0x5}: foo
# CHECK-NEXT: {sp: 16, bp: -16, info: 0x15}: foo
# CHECK-NEXT: {sp: 16, bp: -16, info: 0x14}: foo
# CHECK-NEXT: {sp: 8, bp: 0, info: 0x5}: foo
# CHECK-NEXT: {sp: 0, bp: 0, info: 0x0}: bar
# CHECK-NEXT: {sp: 0, bp: 0, info: 0x0}: bar
# CHECK: BOLT-INFO: parsed 9 ORC entries

.text
.globl _start
.type _start, %function
_start:
# CHECK: Binary Function "_start"

call foo
# CHECK: callq foo # ORC: {sp: 8, bp: 0, info: 0x5}
Expand All @@ -32,6 +58,8 @@ _start:
.globl foo
.type foo, %function
foo:
# CHECK: Binary Function "foo"

push %rbp
# CHECK: pushq %rbp # ORC: {sp: 8, bp: 0, info: 0x5}
.L1:
Expand All @@ -40,12 +68,16 @@ foo:
.L2:
pop %rbp
# CHECK: popq %rbp # ORC: {sp: 16, bp: -16, info: 0x14}
nop
.L3:
ret
# CHECK: retq # ORC: {sp: 8, bp: 0, info: 0x5}
.size foo, .-foo

.globl bar
.type bar, %function
bar:
# CHECK: Binary Function "bar"
ret
## Same ORC info propagated from foo above.
# CHECK: retq # ORC: {sp: 8, bp: 0, info: 0x5}
Expand Down
59 changes: 59 additions & 0 deletions bolt/test/X86/linux-static-calls.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# REQUIRES: system-linux

## Check that BOLT correctly updates the Linux kernel static calls table.

# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o
# RUN: %clang %cflags -nostdlib %t.o -o %t.exe \
# RUN: -Wl,--image-base=0xffffffff80000000,--no-dynamic-linker,--no-eh-frame-hdr

## Verify static calls bindings to instructions.

# RUN: llvm-bolt %t.exe --print-normalized -o %t.out --keep-nops=0 \
# RUN: --bolt-info=0 |& FileCheck %s

## Verify the bindings again on the rewritten binary with nops removed.

# RUN: llvm-bolt %t.out -o %t.out.1 --print-normalized |& FileCheck %s

# CHECK: BOLT-INFO: Linux kernel binary detected
# CHECK: BOLT-INFO: parsed 2 static call entries

.text
.globl _start
.type _start, %function
_start:
# CHECK: Binary Function "_start"
nop
.L0:
call foo
# CHECK: callq foo # {{.*}} StaticCall: 1
nop
.L1:
jmp foo
# CHECK: jmp foo # {{.*}} StaticCall: 2
.size _start, .-_start

.globl foo
.type foo, %function
foo:
ret
.size foo, .-foo


## Static call table.
.rodata
.globl __start_static_call_sites
.type __start_static_call_sites, %object
__start_static_call_sites:
.long .L0 - .
.long 0
.long .L1 - .
.long 0

.globl __stop_static_call_sites
.type __stop_static_call_sites, %object
__stop_static_call_sites:

## Fake Linux Kernel sections.
.section __ksymtab,"a",@progbits
.section __ksymtab_gpl,"a",@progbits
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ void NonZeroEnumToBoolConversionCheck::registerMatchers(MatchFinder *Finder) {
EnumIgnoreList)))
.bind("enum"))))),
unless(declRefExpr(to(enumConstantDecl()))),
unless(ignoringImplicit(ExcludedOperators)))),
unless(ignoringParenImpCasts(ExcludedOperators)))),
unless(hasAncestor(staticAssertDecl())))
.bind("cast"),
this);
Expand Down
10 changes: 7 additions & 3 deletions clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -706,13 +706,17 @@ void LoopConvertCheck::doConversion(
ReplaceText = Usage.Kind == Usage::UK_MemberThroughArrow
? VarNameOrStructuredBinding + "."
: VarNameOrStructuredBinding;
auto Parents = Context->getParents(*Usage.Expression);
const DynTypedNodeList Parents = Context->getParents(*Usage.Expression);
if (Parents.size() == 1) {
if (const auto *Paren = Parents[0].get<ParenExpr>()) {
// Usage.Expression will be replaced with the new index variable,
// and parenthesis around a simple DeclRefExpr can always be
// removed.
Range = Paren->getSourceRange();
// removed except in case of a `sizeof` operator call.
const DynTypedNodeList GrandParents = Context->getParents(*Paren);
if (GrandParents.size() != 1 ||
GrandParents[0].get<UnaryExprOrTypeTraitExpr>() == nullptr) {
Range = Paren->getSourceRange();
}
} else if (const auto *UOP = Parents[0].get<UnaryOperator>()) {
// If we are taking the address of the loop variable, then we must
// not use a copy, as it would mean taking the address of the loop's
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1408,13 +1408,16 @@ const IdentifierNamingCheck::FileStyle &
IdentifierNamingCheck::getStyleForFile(StringRef FileName) const {
if (!GetConfigPerFile)
return *MainFileStyle;
StringRef Parent = llvm::sys::path::parent_path(FileName);

SmallString<128> RealFileName;
llvm::sys::fs::real_path(FileName, RealFileName);
StringRef Parent = llvm::sys::path::parent_path(RealFileName);
auto Iter = NamingStylesCache.find(Parent);
if (Iter != NamingStylesCache.end())
return Iter->getValue();

llvm::StringRef CheckName = getID();
ClangTidyOptions Options = Context->getOptionsForFile(FileName);
ClangTidyOptions Options = Context->getOptionsForFile(RealFileName);
if (Options.Checks && GlobList(*Options.Checks).contains(CheckName)) {
auto It = NamingStylesCache.try_emplace(
Parent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,16 +151,29 @@ StringRef getEquivalentBoolLiteralForExpr(const Expr *Expression,
return {};
}

bool needsSpacePrefix(SourceLocation Loc, ASTContext &Context) {
SourceRange PrefixRange(Loc.getLocWithOffset(-1), Loc);
StringRef SpaceBeforeStmtStr = Lexer::getSourceText(
CharSourceRange::getCharRange(PrefixRange), Context.getSourceManager(),
Context.getLangOpts(), nullptr);
if (SpaceBeforeStmtStr.empty())
return true;

const StringRef AllowedCharacters(" \t\n\v\f\r(){}[]<>;,+=-|&~!^*/");
return !AllowedCharacters.contains(SpaceBeforeStmtStr.back());
}

void fixGenericExprCastFromBool(DiagnosticBuilder &Diag,
const ImplicitCastExpr *Cast,
ASTContext &Context, StringRef OtherType) {
const Expr *SubExpr = Cast->getSubExpr();
bool NeedParens = !isa<ParenExpr>(SubExpr);
const bool NeedParens = !isa<ParenExpr>(SubExpr->IgnoreImplicit());
const bool NeedSpace = needsSpacePrefix(Cast->getBeginLoc(), Context);

Diag << FixItHint::CreateInsertion(
Cast->getBeginLoc(),
(Twine("static_cast<") + OtherType + ">" + (NeedParens ? "(" : ""))
.str());
Cast->getBeginLoc(), (Twine() + (NeedSpace ? " " : "") + "static_cast<" +
OtherType + ">" + (NeedParens ? "(" : ""))
.str());

if (NeedParens) {
SourceLocation EndLoc = Lexer::getLocForEndOfToken(
Expand Down
44 changes: 40 additions & 4 deletions clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,8 @@ bool eligibleForExtraction(const SelectionTree::Node *N) {
// Extracting Exprs like a = 1 gives placeholder = a = 1 which isn't useful.
// FIXME: we could still hoist the assignment, and leave the variable there?
ParsedBinaryOperator BinOp;
if (BinOp.parse(*N) && BinaryOperator::isAssignmentOp(BinOp.Kind))
bool IsBinOp = BinOp.parse(*N);
if (IsBinOp && BinaryOperator::isAssignmentOp(BinOp.Kind))
return false;

const SelectionTree::Node &OuterImplicit = N->outerImplicit();
Expand All @@ -483,13 +484,48 @@ bool eligibleForExtraction(const SelectionTree::Node *N) {
OuterImplicit.ASTNode.get<Expr>()))
return false;

std::function<bool(const SelectionTree::Node *)> IsFullySelected =
[&](const SelectionTree::Node *N) {
if (N->ASTNode.getSourceRange().isValid() &&
N->Selected != SelectionTree::Complete)
return false;
for (const auto *Child : N->Children) {
if (!IsFullySelected(Child))
return false;
}
return true;
};
auto ExprIsFullySelectedTargetNode = [&](const Expr *E) {
if (E != OuterImplicit.ASTNode.get<Expr>())
return false;

// The above condition is the only relevant one except for binary operators.
// Without the following code, we would fail to offer extraction for e.g.:
// int x = 1 + 2 + [[3 + 4 + 5]];
// See the documentation of ParsedBinaryOperator for further details.
if (!IsBinOp)
return true;
return IsFullySelected(N);
};

// Disable extraction of full RHS on assignment operations, e.g:
// auto x = [[RHS_EXPR]];
// x = [[RHS_EXPR]];
// This would just result in duplicating the code.
if (const auto *BO = Parent->ASTNode.get<BinaryOperator>()) {
if (BO->isAssignmentOp() &&
BO->getRHS() == OuterImplicit.ASTNode.get<Expr>())
if (BO->isAssignmentOp() && ExprIsFullySelectedTargetNode(BO->getRHS()))
return false;
}

// The same logic as for assignments applies to initializations.
// However, we do allow extracting the RHS of an init capture, as it is
// a valid use case to move non-trivial expressions out of the capture clause.
// FIXME: In that case, the extracted variable should be captured directly,
// rather than an explicit copy.
if (const auto *Decl = Parent->ASTNode.get<VarDecl>()) {
if (!Decl->isInitCapture() &&
ExprIsFullySelectedTargetNode(Decl->getInit())) {
return false;
}
}

return true;
Expand Down
27 changes: 15 additions & 12 deletions clang-tools-extra/clangd/unittests/tweaks/ExtractVariableTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ TEST_F(ExtractVariableTest, Test) {
return [[[[t.b[[a]]r]]([[t.z]])]];
}
void f() {
int a = [[5 +]] [[4 * [[[[xyz]]()]]]];
int a = 5 + [[4 * [[[[xyz]]()]]]];
// multivariable initialization
if(1)
int x = [[1]], y = [[a + 1]], a = [[1]], z = a + 1;
int x = [[1]] + 1, y = a + [[1]], a = [[1]] + 2, z = a + 1;
// if without else
if([[1]])
a = [[1]] + 1;
Expand Down Expand Up @@ -61,7 +61,7 @@ TEST_F(ExtractVariableTest, Test) {
ExtraArgs = {"-xc"};
const char *AvailableC = R"cpp(
void foo() {
int x = [[1]];
int x = [[1]] + 1;
})cpp";
EXPECT_AVAILABLE(AvailableC);

Expand All @@ -79,7 +79,7 @@ TEST_F(ExtractVariableTest, Test) {
@end
@implementation Foo
- (void)method {
int x = [[1 + 2]];
int x = [[1]] + 2;
}
@end)cpp";
EXPECT_AVAILABLE(AvailableObjC);
Expand All @@ -103,6 +103,9 @@ TEST_F(ExtractVariableTest, Test) {
}
int z = [[1]];
} t;
int x = [[1 + 2]];
int y;
y = [[1 + 2]];
return [[t]].bar([[t]].z);
}
void v() { return; }
Expand Down Expand Up @@ -430,8 +433,8 @@ TEST_F(ExtractVariableTest, Test) {
int member = 42;
};
)cpp"},
{R"cpp(void f() { auto x = [[ [](){ return 42; }]]; })cpp",
R"cpp(void f() { auto placeholder = [](){ return 42; }; auto x = placeholder; })cpp"},
{R"cpp(void f() { auto x = +[[ [](){ return 42; }]]; })cpp",
R"cpp(void f() { auto placeholder = [](){ return 42; }; auto x = + placeholder; })cpp"},
{R"cpp(
template <typename T>
auto sink(T f) { return f(); }
Expand Down Expand Up @@ -515,13 +518,13 @@ TEST_F(ExtractVariableTest, Test) {
{R"cpp(
template <typename ...Ts>
void foo(Ts ...args) {
auto x = [[ [&args...]() {} ]];
auto x = +[[ [&args...]() {} ]];
}
)cpp",
R"cpp(
template <typename ...Ts>
void foo(Ts ...args) {
auto placeholder = [&args...]() {}; auto x = placeholder ;
auto placeholder = [&args...]() {}; auto x = + placeholder ;
}
)cpp"},
{R"cpp(
Expand All @@ -533,7 +536,7 @@ TEST_F(ExtractVariableTest, Test) {
int main() {
Coordinates c = {};
const auto [x, y] = c;
auto f = [[ [&]() { return x + y; } ]];
auto f = [[ [&]() { return x + y; } ]]();
}
)cpp",
R"cpp(
Expand All @@ -545,7 +548,7 @@ TEST_F(ExtractVariableTest, Test) {
int main() {
Coordinates c = {};
const auto [x, y] = c;
auto placeholder = [&]() { return x + y; }; auto f = placeholder ;
auto placeholder = [&]() { return x + y; }; auto f = placeholder ();
}
)cpp"},
{R"cpp(
Expand All @@ -557,7 +560,7 @@ TEST_F(ExtractVariableTest, Test) {
int main() {
Coordinates c = {};
if (const auto [x, y] = c; x > y) {
auto f = [[ [&]() { return x + y; } ]];
auto f = [[ [&]() { return x + y; } ]]();
}
}
)cpp",
Expand All @@ -570,7 +573,7 @@ TEST_F(ExtractVariableTest, Test) {
int main() {
Coordinates c = {};
if (const auto [x, y] = c; x > y) {
auto placeholder = [&]() { return x + y; }; auto f = placeholder ;
auto placeholder = [&]() { return x + y; }; auto f = placeholder ();
}
}
)cpp"},
Expand Down
19 changes: 19 additions & 0 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ New check aliases
Changes in existing checks
^^^^^^^^^^^^^^^^^^^^^^^^^^

- Improved :doc:`bugprone-non-zero-enum-to-bool-conversion
<clang-tidy/checks/bugprone/non-zero-enum-to-bool-conversion>` check by
eliminating false positives resulting from direct usage of bitwise operators
within parentheses.

- Improved :doc:`bugprone-suspicious-include
<clang-tidy/checks/bugprone/suspicious-include>` check by replacing the local
options `HeaderFileExtensions` and `ImplementationFileExtensions` by the
Expand Down Expand Up @@ -165,14 +170,28 @@ Changes in existing checks
`AllowStringArrays` option, enabling the exclusion of array types with deduced
length initialized from string literals.

- Improved :doc:`modernize-loop-convert
<clang-tidy/checks/modernize/loop-convert>` check by ensuring that fix-its
don't remove parentheses used in ``sizeof`` calls when they have array index
accesses as arguments.

- Improved :doc:`modernize-use-override
<clang-tidy/checks/modernize/use-override>` check to also remove any trailing
whitespace when deleting the ``virtual`` keyword.

- Improved :doc:`readability-implicit-bool-conversion
<clang-tidy/checks/readability/implicit-bool-conversion>` check to provide
valid fix suggestions for ``static_cast`` without a preceding space and
fixed problem with duplicate parentheses in double implicit casts.

- Improved :doc:`readability-redundant-inline-specifier
<clang-tidy/checks/readability/redundant-inline-specifier>` check to properly
emit warnings for static data member with an in-class initializer.

- Improved :doc:`readability-identifier-naming
<clang-tidy/checks/readability/identifier-naming>` check in `GetConfigPerFile`
mode by resolving symbolic links to header files.

Removed checks
^^^^^^^^^^^^^^

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ CustomOperatorEnum operator&(CustomOperatorEnum a, CustomOperatorEnum b) { retur

void testCustomOperator(CustomOperatorEnum e) {
if (e & E1) {}
if ((e & E1)) {}
if (!(e & E1)) {}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,19 @@ void f() {
// CHECK-FIXES-NEXT: printf("Fibonacci number %d has address %p\n", I, &I);
// CHECK-FIXES-NEXT: Sum += I + 2;

int Matrix[N][12];
unsigned size = 0;
for (int I = 0; I < N; ++I) {
size += sizeof(Matrix[I]);
size += sizeof Matrix[I];
size += sizeof((Matrix[I]));
}
// CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
// CHECK-FIXES: for (auto & I : Matrix)
// CHECK-FIXES-NEXT: size += sizeof(I);
// CHECK-FIXES-NEXT: size += sizeof I;
// CHECK-FIXES-NEXT: size += sizeof(I);

Val Teas[N];
for (int I = 0; I < N; ++I) {
Teas[I].g();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Checks: readability-identifier-naming
CheckOptions:
readability-identifier-naming.GlobalConstantCase: CamelCase
readability-identifier-naming.GlobalConstantPrefix: k
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
const int global_const = 5;
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Specify `-std=c++20` to run test only once becuase test expects changes
// in the header file so it fails if runs multiple times with different
// `-std` flags as check_clang_tidy doesn by default.
//
// RUN: rm -rf %T/symlink
// RUN: cp -r %S/Inputs/identifier-naming/symlink %T/symlink
// RUN: mkdir -p %T/symlink/build
// RUN: ln -s %T/symlink/include/test.h %T/symlink/build/test.h
// RUN: %check_clang_tidy -std=c++20 %s readability-identifier-naming %t -- --header-filter="test.h" --config-file=%S/Inputs/identifier-naming/symlink/include/.clang-tidy -- -I %T/symlink/build
// UNSUPPORTED: system-windows

#include "test.h"

int foo() {
return global_const;
// CHECK-MESSAGES: warning: invalid case style for global constant 'global_const' [readability-identifier-naming]
// CHECK-FIXES: return kGlobalConst;
}
Original file line number Diff line number Diff line change
Expand Up @@ -524,3 +524,12 @@ namespace PR71867 {
// CHECK-FIXES: return (x ? 1 : 0) != 0;
}
}

namespace PR71848 {
int fun() {
bool foo = false;
return( foo );
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: implicit conversion 'bool' -> 'int' [readability-implicit-bool-conversion]
// CHECK-FIXES: return static_cast<int>( foo );
}
}
7 changes: 5 additions & 2 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,9 @@ Improvements to Clang's diagnostics

- Clang now diagnoses friend declarations with an ``enum`` elaborated-type-specifier in language modes after C++98.

- Added diagnostics for C11 keywords being incompatible with language standards
before C11, under a new warning group: ``-Wpre-c11-compat``.

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

Expand Down Expand Up @@ -262,6 +265,8 @@ Bug Fixes to C++ Support
- No longer reject valid use of the ``_Alignas`` specifier when declaring a
local variable, which is supported as a C11 extension in C++. Previously, it
was only accepted at namespace scope but not at local function scope.
- Clang no longer tries to call consteval constructors at runtime when they appear in a member initializer.
(`#782154 <https://github.com/llvm/llvm-project/issues/82154>`_`)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -287,8 +292,6 @@ X86 Support
Arm and AArch64 Support
^^^^^^^^^^^^^^^^^^^^^^^

- Fixed the incorrect definition of the __ARM_ARCH macro for architectures greater than or equal to v8.1.

Android Support
^^^^^^^^^^^^^^^

Expand Down
84 changes: 48 additions & 36 deletions clang/include/clang/Basic/Attr.td

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions clang/include/clang/Basic/DiagnosticCommonKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -356,8 +356,6 @@ def warn_target_unrecognized_env : Warning<
def warn_knl_knm_isa_support_removed : Warning<
"KNL, KNM related Intel Xeon Phi CPU's specific ISA's supports will be removed in LLVM 19.">,
InGroup<DiagGroup<"knl-knm-isa-support-removed">>;
def err_target_unsupported_abi_with_fpu : Error<
"'%0' ABI is not supported with FPU">;

// Source manager
def err_cannot_open_file : Error<"cannot open file '%0': %1">, DefaultFatal;
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,9 @@ def : DiagGroup<"c++1z-compat-mangling", [CXX17CompatMangling]>;
def NoexceptType : DiagGroup<"noexcept-type", [CXX17CompatMangling]>;

// Warnings for C code which is not compatible with previous C standards.
def CPre11Compat : DiagGroup<"pre-c11-compat">;
def CPre11CompatPedantic : DiagGroup<"pre-c11-compat-pedantic",
[CPre11Compat]>;
def CPre23Compat : DiagGroup<"pre-c23-compat">;
def CPre23CompatPedantic : DiagGroup<"pre-c23-compat-pedantic",
[CPre23Compat]>;
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticParseKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,9 @@ def ext_c99_feature : Extension<
"'%0' is a C99 extension">, InGroup<C99>;
def ext_c11_feature : Extension<
"'%0' is a C11 extension">, InGroup<C11>;
def warn_c11_compat_keyword : Warning<
"'%0' is incompatible with C standards before C11">,
InGroup<CPre11Compat>, DefaultIgnore;
def warn_c23_compat_keyword : Warning<
"'%0' is incompatible with C standards before C23">,
InGroup<CPre23Compat>, DefaultIgnore;
Expand Down
2 changes: 0 additions & 2 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -11314,8 +11314,6 @@ def err_omp_wrong_dependency_iterator_type : Error<
def err_target_unsupported_type
: Error<"%0 requires %select{|%2 bit size}1 %3 %select{|return }4type support,"
" but target '%5' does not support it">;
def err_target_unsupported_type_for_abi
: Error<"%0 requires %1 type support, but ABI '%2' does not support it">;
def err_omp_lambda_capture_in_declare_target_not_to : Error<
"variable captured in declare target region must appear in a to clause">;
def err_omp_device_type_mismatch : Error<
Expand Down
8 changes: 0 additions & 8 deletions clang/include/clang/Basic/TargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,6 @@ class TargetInfo : public TransferrableTargetInfo,
bool HasIbm128;
bool HasLongDouble;
bool HasFPReturn;
bool HasFPTypes;
bool HasStrictFP;

unsigned char MaxAtomicPromoteWidth, MaxAtomicInlineWidth;
Expand Down Expand Up @@ -690,9 +689,6 @@ class TargetInfo : public TransferrableTargetInfo,
/// on this target.
virtual bool hasFPReturn() const { return HasFPReturn; }

/// Determine whether floating point types are supported for this target.
virtual bool hasFPTypes() const { return HasFPTypes; }

/// Determine whether constrained floating point is supported on this target.
virtual bool hasStrictFP() const { return HasStrictFP; }

Expand Down Expand Up @@ -1335,10 +1331,6 @@ class TargetInfo : public TransferrableTargetInfo,
return false;
}

/// Make changes to the supported types which depend on both the target
/// features and ABI.
virtual void setSupportedArgTypes() {}

/// Use the specified unit for FP math.
///
/// \return False on error (invalid unit name).
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -1122,6 +1122,8 @@ class Parser : public CodeCompletionHandler {
void checkCompoundToken(SourceLocation FirstTokLoc,
tok::TokenKind FirstTokKind, CompoundToken Op);

void diagnoseUseOfC11Keyword(const Token &Tok);

public:
//===--------------------------------------------------------------------===//
// Scope manipulation
Expand Down
149 changes: 88 additions & 61 deletions clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1157,8 +1157,13 @@ bool ByteCodeExprGen<Emitter>::VisitMemberExpr(const MemberExpr *E) {
if (DiscardResult)
return this->discard(Base);

if (!this->delegate(Base))
return false;
if (Initializing) {
if (!this->delegate(Base))
return false;
} else {
if (!this->visit(Base))
return false;
}

// Base above gives us a pointer on the stack.
// TODO: Implement non-FieldDecl members.
Expand Down Expand Up @@ -1468,7 +1473,7 @@ bool ByteCodeExprGen<Emitter>::VisitCompoundAssignOperator(
std::optional<PrimType> LHSComputationT =
classify(E->getComputationLHSType());
std::optional<PrimType> LT = classify(LHS->getType());
std::optional<PrimType> RT = classify(E->getComputationResultType());
std::optional<PrimType> RT = classify(RHS->getType());
std::optional<PrimType> ResultT = classify(E->getType());

if (!LT || !RT || !ResultT || !LHSComputationT)
Expand Down Expand Up @@ -1716,6 +1721,9 @@ bool ByteCodeExprGen<Emitter>::VisitTypeTraitExpr(const TypeTraitExpr *E) {

template <class Emitter>
bool ByteCodeExprGen<Emitter>::VisitLambdaExpr(const LambdaExpr *E) {
if (DiscardResult)
return true;

assert(Initializing);
const Record *R = P.getOrCreateRecord(E->getLambdaClass());

Expand Down Expand Up @@ -1848,6 +1856,8 @@ bool ByteCodeExprGen<Emitter>::VisitCXXConstructExpr(

// Immediately call the destructor if we have to.
if (DiscardResult) {
if (!this->emitRecordDestruction(getRecord(E->getType())))
return false;
if (!this->emitPopPtr(E))
return false;
}
Expand Down Expand Up @@ -2146,6 +2156,12 @@ bool ByteCodeExprGen<Emitter>::VisitConceptSpecializationExpr(
return this->emitConstBool(E->isSatisfied(), E);
}

template <class Emitter>
bool ByteCodeExprGen<Emitter>::VisitCXXRewrittenBinaryOperator(
const CXXRewrittenBinaryOperator *E) {
return this->delegate(E->getSemanticForm());
}

template <class Emitter> bool ByteCodeExprGen<Emitter>::discard(const Expr *E) {
if (E->containsErrors())
return false;
Expand Down Expand Up @@ -2463,17 +2479,6 @@ bool ByteCodeExprGen<Emitter>::dereferenceVar(
}
}

// If the declaration is a constant value, emit it here even
// though the declaration was not evaluated in the current scope.
// The access mode can only be read in this case.
if (!DiscardResult && AK == DerefKind::Read) {
if (VD->hasLocalStorage() && VD->hasInit() && !VD->isConstexpr()) {
QualType VT = VD->getType();
if (VT.isConstQualified() && VT->isFundamentalType())
return this->visit(VD->getInit());
}
}

// Value cannot be produced - try to emit pointer.
return visit(LV) && Indirect(T);
}
Expand Down Expand Up @@ -2744,10 +2749,9 @@ bool ByteCodeExprGen<Emitter>::visitVarDecl(const VarDecl *VD) {
return this->emitSetLocal(*VarT, Offset, VD);
}
} else {
if (std::optional<unsigned> Offset = this->allocateLocal(VD)) {
if (Init)
return this->visitLocalInitializer(Init, *Offset);
}
if (std::optional<unsigned> Offset = this->allocateLocal(VD))
return !Init || this->visitLocalInitializer(Init, *Offset);
return false;
}
return true;
}
Expand Down Expand Up @@ -2822,14 +2826,28 @@ bool ByteCodeExprGen<Emitter>::VisitCallExpr(const CallExpr *E) {
}
}

auto Args = E->arguments();
// Calling a static operator will still
// pass the instance, but we don't need it.
// Discard it here.
if (isa<CXXOperatorCallExpr>(E)) {
if (const auto *MD =
dyn_cast_if_present<CXXMethodDecl>(E->getDirectCallee());
MD && MD->isStatic()) {
if (!this->discard(E->getArg(0)))
return false;
Args = drop_begin(Args, 1);
}
}

// Add the (optional, implicit) This pointer.
if (const auto *MC = dyn_cast<CXXMemberCallExpr>(E)) {
if (!this->visit(MC->getImplicitObjectArgument()))
return false;
}

// Put arguments on the stack.
for (const auto *Arg : E->arguments()) {
for (const auto *Arg : Args) {
if (!this->visit(Arg))
return false;
}
Expand Down Expand Up @@ -3365,45 +3383,8 @@ bool ByteCodeExprGen<Emitter>::emitComplexReal(const Expr *SubExpr) {
return true;
}

/// When calling this, we have a pointer of the local-to-destroy
/// on the stack.
/// Emit destruction of record types (or arrays of record types).
template <class Emitter>
bool ByteCodeExprGen<Emitter>::emitRecordDestruction(const Descriptor *Desc) {
assert(Desc);
assert(!Desc->isPrimitive());
assert(!Desc->isPrimitiveArray());

// Arrays.
if (Desc->isArray()) {
const Descriptor *ElemDesc = Desc->ElemDesc;
assert(ElemDesc);

// Don't need to do anything for these.
if (ElemDesc->isPrimitiveArray())
return this->emitPopPtr(SourceInfo{});

// If this is an array of record types, check if we need
// to call the element destructors at all. If not, try
// to save the work.
if (const Record *ElemRecord = ElemDesc->ElemRecord) {
if (const CXXDestructorDecl *Dtor = ElemRecord->getDestructor();
!Dtor || Dtor->isTrivial())
return this->emitPopPtr(SourceInfo{});
}

for (ssize_t I = Desc->getNumElems() - 1; I >= 0; --I) {
if (!this->emitConstUint64(I, SourceInfo{}))
return false;
if (!this->emitArrayElemPtrUint64(SourceInfo{}))
return false;
if (!this->emitRecordDestruction(ElemDesc))
return false;
}
return this->emitPopPtr(SourceInfo{});
}

const Record *R = Desc->ElemRecord;
bool ByteCodeExprGen<Emitter>::emitRecordDestruction(const Record *R) {
assert(R);
// First, destroy all fields.
for (const Record::Field &Field : llvm::reverse(R->fields())) {
Expand All @@ -3413,7 +3394,9 @@ bool ByteCodeExprGen<Emitter>::emitRecordDestruction(const Descriptor *Desc) {
return false;
if (!this->emitGetPtrField(Field.Offset, SourceInfo{}))
return false;
if (!this->emitRecordDestruction(D))
if (!this->emitDestruction(D))
return false;
if (!this->emitPopPtr(SourceInfo{}))
return false;
}
}
Expand All @@ -3437,13 +3420,57 @@ bool ByteCodeExprGen<Emitter>::emitRecordDestruction(const Descriptor *Desc) {
for (const Record::Base &Base : llvm::reverse(R->bases())) {
if (!this->emitGetPtrBase(Base.Offset, SourceInfo{}))
return false;
if (!this->emitRecordDestruction(Base.Desc))
if (!this->emitRecordDestruction(Base.R))
return false;
if (!this->emitPopPtr(SourceInfo{}))
return false;
}

// FIXME: Virtual bases.
return true;
}
/// When calling this, we have a pointer of the local-to-destroy
/// on the stack.
/// Emit destruction of record types (or arrays of record types).
template <class Emitter>
bool ByteCodeExprGen<Emitter>::emitDestruction(const Descriptor *Desc) {
assert(Desc);
assert(!Desc->isPrimitive());
assert(!Desc->isPrimitiveArray());

// Arrays.
if (Desc->isArray()) {
const Descriptor *ElemDesc = Desc->ElemDesc;
assert(ElemDesc);

// Don't need to do anything for these.
if (ElemDesc->isPrimitiveArray())
return true;

// If this is an array of record types, check if we need
// to call the element destructors at all. If not, try
// to save the work.
if (const Record *ElemRecord = ElemDesc->ElemRecord) {
if (const CXXDestructorDecl *Dtor = ElemRecord->getDestructor();
!Dtor || Dtor->isTrivial())
return true;
}

for (ssize_t I = Desc->getNumElems() - 1; I >= 0; --I) {
if (!this->emitConstUint64(I, SourceInfo{}))
return false;
if (!this->emitArrayElemPtrUint64(SourceInfo{}))
return false;
if (!this->emitDestruction(ElemDesc))
return false;
if (!this->emitPopPtr(SourceInfo{}))
return false;
}
return true;
}

// Remove the instance pointer.
return this->emitPopPtr(SourceInfo{});
assert(Desc->ElemRecord);
return this->emitRecordDestruction(Desc->ElemRecord);
}

namespace clang {
Expand Down
7 changes: 5 additions & 2 deletions clang/lib/AST/Interp/ByteCodeExprGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
bool VisitCXXUuidofExpr(const CXXUuidofExpr *E);
bool VisitRequiresExpr(const RequiresExpr *E);
bool VisitConceptSpecializationExpr(const ConceptSpecializationExpr *E);
bool VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator *E);

protected:
bool visitExpr(const Expr *E) override;
Expand Down Expand Up @@ -289,7 +290,8 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,

bool emitComplexReal(const Expr *SubExpr);

bool emitRecordDestruction(const Descriptor *Desc);
bool emitRecordDestruction(const Record *R);
bool emitDestruction(const Descriptor *Desc);
unsigned collectBaseOffset(const RecordType *BaseType,
const RecordType *DerivedType);

Expand Down Expand Up @@ -401,7 +403,8 @@ template <class Emitter> class LocalScope : public VariableScope<Emitter> {
for (Scope::Local &Local : this->Ctx->Descriptors[*Idx]) {
if (!Local.Desc->isPrimitive() && !Local.Desc->isPrimitiveArray()) {
this->Ctx->emitGetPtrLocal(Local.Offset, SourceInfo{});
this->Ctx->emitRecordDestruction(Local.Desc);
this->Ctx->emitDestruction(Local.Desc);
this->Ctx->emitPopPtr(SourceInfo{});
removeIfStoredOpaqueValue(Local);
}
}
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/AST/Interp/Descriptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ static void moveArrayDesc(Block *B, const std::byte *Src, std::byte *Dst,
static void ctorRecord(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
bool IsActive, const Descriptor *D) {
const bool IsUnion = D->ElemRecord->isUnion();
auto CtorSub = [=](unsigned SubOff, Descriptor *F, bool IsBase) {
auto CtorSub = [=](unsigned SubOff, const Descriptor *F, bool IsBase) {
auto *Desc = reinterpret_cast<InlineDescriptor *>(Ptr + SubOff) - 1;
Desc->Offset = SubOff;
Desc->Desc = F;
Expand All @@ -161,7 +161,7 @@ static void ctorRecord(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
}

static void dtorRecord(Block *B, std::byte *Ptr, const Descriptor *D) {
auto DtorSub = [=](unsigned SubOff, Descriptor *F) {
auto DtorSub = [=](unsigned SubOff, const Descriptor *F) {
if (auto Fn = F->DtorFn)
Fn(B, Ptr + SubOff, F);
};
Expand Down
1 change: 0 additions & 1 deletion clang/lib/AST/Interp/EvalEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,6 @@ template <> bool EvalEmitter::emitRet<PT_FnPtr>(const SourceInfo &Info) {
if (!isActive())
return true;
// Function pointers cannot be converted to rvalues.
assert(!ConvertResultToRValue);
EvalResult.setFunctionPointer(S.Stk.pop<FunctionPointer>());
return true;
}
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/AST/Interp/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -1579,6 +1579,11 @@ inline bool SubPtr(InterpState &S, CodePtr OpPC) {
return false;
}

if (LHS.isZero() && RHS.isZero()) {
S.Stk.push<T>();
return true;
}

T A = T::from(LHS.getIndex());
T B = T::from(RHS.getIndex());
return AddSubMulHelper<T, T::sub, std::minus>(S, OpPC, A.bitWidth(), A, B);
Expand Down
46 changes: 29 additions & 17 deletions clang/lib/AST/Interp/Program.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,9 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) {
if (!RD)
return nullptr;

if (!RD->isCompleteDefinition())
return nullptr;

// Deduplicate records.
if (auto It = Records.find(RD); It != Records.end())
return It->second;
Expand All @@ -247,7 +250,8 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) {
unsigned VirtSize = 0;

// Helper to get a base descriptor.
auto GetBaseDesc = [this](const RecordDecl *BD, Record *BR) -> Descriptor * {
auto GetBaseDesc = [this](const RecordDecl *BD,
const Record *BR) -> const Descriptor * {
if (!BR)
return nullptr;
return allocateDescriptor(BD, BR, std::nullopt, /*isConst=*/false,
Expand All @@ -258,31 +262,39 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) {
// Reserve space for base classes.
Record::BaseList Bases;
Record::VirtualBaseList VirtBases;
if (auto *CD = dyn_cast<CXXRecordDecl>(RD)) {
if (const auto *CD = dyn_cast<CXXRecordDecl>(RD)) {

for (const CXXBaseSpecifier &Spec : CD->bases()) {
if (Spec.isVirtual())
continue;

const RecordDecl *BD = Spec.getType()->castAs<RecordType>()->getDecl();
Record *BR = getOrCreateRecord(BD);
if (Descriptor *Desc = GetBaseDesc(BD, BR)) {
BaseSize += align(sizeof(InlineDescriptor));
Bases.push_back({BD, BaseSize, Desc, BR});
BaseSize += align(BR->getSize());
continue;
// In error cases, the base might not be a RecordType.
if (const auto *RT = Spec.getType()->getAs<RecordType>()) {
const RecordDecl *BD = RT->getDecl();
const Record *BR = getOrCreateRecord(BD);

if (const Descriptor *Desc = GetBaseDesc(BD, BR)) {
BaseSize += align(sizeof(InlineDescriptor));
Bases.push_back({BD, BaseSize, Desc, BR});
BaseSize += align(BR->getSize());
continue;
}
}
return nullptr;
}

for (const CXXBaseSpecifier &Spec : CD->vbases()) {
const RecordDecl *BD = Spec.getType()->castAs<RecordType>()->getDecl();
Record *BR = getOrCreateRecord(BD);

if (Descriptor *Desc = GetBaseDesc(BD, BR)) {
VirtSize += align(sizeof(InlineDescriptor));
VirtBases.push_back({BD, VirtSize, Desc, BR});
VirtSize += align(BR->getSize());
continue;
if (const auto *RT = Spec.getType()->getAs<RecordType>()) {
const RecordDecl *BD = RT->getDecl();
const Record *BR = getOrCreateRecord(BD);

if (const Descriptor *Desc = GetBaseDesc(BD, BR)) {
VirtSize += align(sizeof(InlineDescriptor));
VirtBases.push_back({BD, VirtSize, Desc, BR});
VirtSize += align(BR->getSize());
continue;
}
}
return nullptr;
}
Expand All @@ -298,7 +310,7 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) {
QualType FT = FD->getType();
const bool IsConst = FT.isConstQualified();
const bool IsMutable = FD->isMutable();
Descriptor *Desc;
const Descriptor *Desc;
if (std::optional<PrimType> T = Ctx.classify(FT)) {
Desc = createDescriptor(FD, *T, std::nullopt, IsConst,
/*isTemporary=*/false, IsMutable);
Expand Down
11 changes: 5 additions & 6 deletions clang/lib/AST/Interp/Record.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,16 @@ class Record final {
struct Field {
const FieldDecl *Decl;
unsigned Offset;
Descriptor *Desc;
const Descriptor *Desc;
bool isBitField() const { return Decl->isBitField(); }
};

/// Describes a base class.
struct Base {
const RecordDecl *Decl;
unsigned Offset;
Descriptor *Desc;
Record *R;
const Descriptor *Desc;
const Record *R;
};

/// Mapping from identifiers to field descriptors.
Expand Down Expand Up @@ -80,7 +80,6 @@ class Record final {

unsigned getNumFields() const { return Fields.size(); }
const Field *getField(unsigned I) const { return &Fields[I]; }
Field *getField(unsigned I) { return &Fields[I]; }

using const_base_iter = BaseList::const_iterator;
llvm::iterator_range<const_base_iter> bases() const {
Expand Down Expand Up @@ -120,9 +119,9 @@ class Record final {
VirtualBaseList VirtualBases;

/// Mapping from declarations to bases.
llvm::DenseMap<const RecordDecl *, Base *> BaseMap;
llvm::DenseMap<const RecordDecl *, const Base *> BaseMap;
/// Mapping from field identifiers to descriptors.
llvm::DenseMap<const FieldDecl *, Field *> FieldMap;
llvm::DenseMap<const FieldDecl *, const Field *> FieldMap;
/// Mapping from declarations to virtual bases.
llvm::DenseMap<const RecordDecl *, Base *> VirtualBaseMap;
/// Size of the structure.
Expand Down
76 changes: 31 additions & 45 deletions clang/lib/Analysis/UnsafeBufferUsage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ isInUnspecifiedPointerContext(internal::Matcher<Stmt> InnerMatcher) {
// clang-format off
auto CallArgMatcher = callExpr(
forEachArgumentWithParamType(
InnerMatcher,
InnerMatcher,
isAnyPointer() /* array also decays to pointer type*/),
unless(callee(
functionDecl(hasAttr(attr::UnsafeBufferUsage)))));
Expand Down Expand Up @@ -1677,15 +1677,6 @@ std::string getUserFillPlaceHolder(StringRef HintTextToUser = "placeholder") {
return s;
}

// Return the text representation of the given `APInt Val`:
static std::string getAPIntText(APInt Val) {
SmallVector<char> Txt;
Val.toString(Txt, 10, true);
// APInt::toString does not add '\0' to the end of the string for us:
Txt.push_back('\0');
return Txt.data();
}

// Return the source location of the last character of the AST `Node`.
template <typename NodeTy>
static std::optional<SourceLocation>
Expand Down Expand Up @@ -2152,15 +2143,18 @@ UPCPreIncrementGadget::getFixits(const FixitStrategy &S) const {
// In many cases, this function cannot figure out the actual extent `S`. It
// then will use a place holder to replace `S` to ask users to fill `S` in. The
// initializer shall be used to initialize a variable of type `std::span<T>`.
// In some cases (e. g. constant size array) the initializer should remain
// unchanged and the function returns empty list. In case the function can't
// provide the right fixit it will return nullopt.
//
// FIXME: Support multi-level pointers
//
// Parameters:
// `Init` a pointer to the initializer expression
// `Ctx` a reference to the ASTContext
static FixItList
static std::optional<FixItList>
FixVarInitializerWithSpan(const Expr *Init, ASTContext &Ctx,
const StringRef UserFillPlaceHolder) {
const StringRef UserFillPlaceHolder) {
const SourceManager &SM = Ctx.getSourceManager();
const LangOptions &LangOpts = Ctx.getLangOpts();

Expand All @@ -2176,11 +2170,11 @@ FixVarInitializerWithSpan(const Expr *Init, ASTContext &Ctx,
std::optional<SourceLocation> InitLocation =
getEndCharLoc(Init, SM, LangOpts);
if (!InitLocation)
return {};
return std::nullopt;

SourceRange SR(Init->getBeginLoc(), *InitLocation);

return {FixItHint::CreateRemoval(SR)};
return FixItList{FixItHint::CreateRemoval(SR)};
}

FixItList FixIts{};
Expand All @@ -2199,19 +2193,18 @@ FixVarInitializerWithSpan(const Expr *Init, ASTContext &Ctx,
if (!Ext->HasSideEffects(Ctx)) {
std::optional<StringRef> ExtentString = getExprText(Ext, SM, LangOpts);
if (!ExtentString)
return {};
return std::nullopt;
ExtentText = *ExtentString;
}
} else if (!CxxNew->isArray())
// Although the initializer is not allocating a buffer, the pointer
// variable could still be used in buffer access operations.
ExtentText = One;
} else if (const auto *CArrTy = Ctx.getAsConstantArrayType(
Init->IgnoreImpCasts()->getType())) {
// In cases `Init` is of an array type after stripping off implicit casts,
// the extent is the array size. Note that if the array size is not a
// constant, we cannot use it as the extent.
ExtentText = getAPIntText(CArrTy->getSize());
} else if (Ctx.getAsConstantArrayType(Init->IgnoreImpCasts()->getType())) {
// std::span has a single parameter constructor for initialization with
// constant size array. The size is auto-deduced as the constructor is a
// function template. The correct fixit is empty - no changes should happen.
return FixItList{};
} else {
// In cases `Init` is of the form `&Var` after stripping of implicit
// casts, where `&` is the built-in operator, the extent is 1.
Expand All @@ -2227,7 +2220,7 @@ FixVarInitializerWithSpan(const Expr *Init, ASTContext &Ctx,
std::optional<SourceLocation> LocPassInit = getPastLoc(Init, SM, LangOpts);

if (!LocPassInit)
return {};
return std::nullopt;

StrBuffer.append(", ");
StrBuffer.append(ExtentText);
Expand Down Expand Up @@ -2301,37 +2294,30 @@ static FixItList fixLocalVarDeclWithSpan(const VarDecl *D, ASTContext &Ctx,
std::stringstream SS;

SS << *SpanTyText;
// Append qualifiers to the type of `D`, if any:
if (D->getType().hasQualifiers())
SS << " " << D->getType().getQualifiers().getAsString();

// The end of the range of the original source that will be replaced
// by `std::span<T> ident`:
SourceLocation EndLocForReplacement = D->getEndLoc();
std::optional<StringRef> IdentText =
getVarDeclIdentifierText(D, Ctx.getSourceManager(), Ctx.getLangOpts());

if (!IdentText) {
DEBUG_NOTE_DECL_FAIL(D, " : failed to locate the identifier");
return {};
}
// Fix the initializer if it exists:
if (const Expr *Init = D->getInit()) {
FixItList InitFixIts =
std::optional<FixItList> InitFixIts =
FixVarInitializerWithSpan(Init, Ctx, UserFillPlaceHolder);
if (InitFixIts.empty())
if (!InitFixIts)
return {};
FixIts.insert(FixIts.end(), std::make_move_iterator(InitFixIts.begin()),
std::make_move_iterator(InitFixIts.end()));
// If the declaration has the form `T *ident = init`, we want to replace
// `T *ident = ` with `std::span<T> ident`:
EndLocForReplacement = Init->getBeginLoc().getLocWithOffset(-1);
}
SS << " " << IdentText->str();
FixIts.insert(FixIts.end(), std::make_move_iterator(InitFixIts->begin()),
std::make_move_iterator(InitFixIts->end()));
}
// For declaration of the form `T * ident = init;`, we want to replace
// `T * ` with `std::span<T>`.
// We ignore CV-qualifiers so for `T * const ident;` we also want to replace
// just `T *` with `std::span<T>`.
const SourceLocation EndLocForReplacement = D->getTypeSpecEndLoc();
if (!EndLocForReplacement.isValid()) {
DEBUG_NOTE_DECL_FAIL(D, " : failed to locate the end of the declaration");
return {};
}
// The only exception is that for `T *ident` we'll add a single space between
// "std::span<T>" and "ident".
// FIXME: The condition is false for identifiers expended from macros.
if (EndLocForReplacement.getLocWithOffset(1) == getVarDeclIdentifierLoc(D))
SS << " ";

FixIts.push_back(FixItHint::CreateReplacement(
SourceRange(D->getBeginLoc(), EndLocForReplacement), SS.str()));
return FixIts;
Expand Down
1 change: 0 additions & 1 deletion clang/lib/Basic/TargetInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : Triple(T) {
HasFullBFloat16 = false;
HasLongDouble = true;
HasFPReturn = true;
HasFPTypes = true;
HasStrictFP = false;
PointerWidth = PointerAlign = 32;
BoolWidth = BoolAlign = 8;
Expand Down
1 change: 0 additions & 1 deletion clang/lib/Basic/Targets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -830,7 +830,6 @@ TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags,
Target->setSupportedOpenCLOpts();
Target->setCommandLineOpenCLOpts();
Target->setMaxAtomicWidth();
Target->setSupportedArgTypes();

if (!Opts->DarwinTargetVariantTriple.empty())
Target->DarwinTargetVariantTriple =
Expand Down
41 changes: 4 additions & 37 deletions clang/lib/Basic/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
//===----------------------------------------------------------------------===//

#include "AArch64.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
Expand Down Expand Up @@ -200,32 +199,13 @@ AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
StringRef AArch64TargetInfo::getABI() const { return ABI; }

bool AArch64TargetInfo::setABI(const std::string &Name) {
if (Name != "aapcs" && Name != "aapcs-soft" && Name != "darwinpcs")
if (Name != "aapcs" && Name != "darwinpcs")
return false;

ABI = Name;
return true;
}

void AArch64TargetInfo::setSupportedArgTypes() {
if (!(FPU & FPUMode) && ABI != "aapcs-soft") {
// When a hard-float ABI is used on a target without an FPU, all
// floating-point argument and return types are rejected because they must
// be passed in FP registers.
HasFPTypes = false;
}
}

bool AArch64TargetInfo::validateTarget(DiagnosticsEngine &Diags) const {
if (hasFeature("fp") && ABI == "aapcs-soft") {
// aapcs-soft is not allowed for targets with an FPU, to avoid there being
// two incomatible ABIs.
Diags.Report(diag::err_target_unsupported_abi_with_fpu) << ABI;
return false;
}
return true;
}

bool AArch64TargetInfo::validateBranchProtection(StringRef Spec, StringRef,
BranchProtectionInfo &BPI,
StringRef &Err) const {
Expand Down Expand Up @@ -387,20 +367,8 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,

// ACLE predefines. Many can only have one possible value on v8 AArch64.
Builder.defineMacro("__ARM_ACLE", "200");

// __ARM_ARCH is defined as an integer value indicating the current ARM ISA.
// For ISAs up to and including v8, __ARM_ARCH is equal to the major version
// number. For ISAs from v8.1 onwards, __ARM_ARCH is scaled up to include the
// minor version number, e.g. for ARM architecture ARMvX.Y:
// __ARM_ARCH = X * 100 + Y.
if (ArchInfo->Version.getMajor() == 8 && ArchInfo->Version.getMinor() == 0)
Builder.defineMacro("__ARM_ARCH",
std::to_string(ArchInfo->Version.getMajor()));
else
Builder.defineMacro("__ARM_ARCH",
std::to_string(ArchInfo->Version.getMajor() * 100 +
ArchInfo->Version.getMinor().value()));

Builder.defineMacro("__ARM_ARCH",
std::to_string(ArchInfo->Version.getMajor()));
Builder.defineMacro("__ARM_ARCH_PROFILE",
std::string("'") + (char)ArchInfo->Profile + "'");

Expand Down Expand Up @@ -706,8 +674,7 @@ bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
return llvm::StringSwitch<bool>(Feature)
.Cases("aarch64", "arm64", "arm", true)
.Case("fmv", HasFMV)
.Case("fp", FPU & FPUMode)
.Cases("neon", "simd", FPU & NeonMode)
.Cases("neon", "fp", "simd", FPU & NeonMode)
.Case("jscvt", HasJSCVT)
.Case("fcma", HasFCMA)
.Case("rng", HasRandGen)
Expand Down
3 changes: 0 additions & 3 deletions clang/lib/Basic/Targets/AArch64.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {

StringRef getABI() const override;
bool setABI(const std::string &Name) override;
void setSupportedArgTypes() override;

bool validateBranchProtection(StringRef Spec, StringRef Arch,
BranchProtectionInfo &BPI,
Expand Down Expand Up @@ -200,8 +199,6 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {
bool hasInt128Type() const override;

bool hasBitIntType() const override { return true; }

bool validateTarget(DiagnosticsEngine &Diags) const override;
};

class LLVM_LIBRARY_VISIBILITY AArch64leTargetInfo : public AArch64TargetInfo {
Expand Down
14 changes: 3 additions & 11 deletions clang/lib/Basic/Targets/ARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,6 @@ void ARMTargetInfo::setArchInfo(llvm::ARM::ArchKind Kind) {
SubArch = llvm::ARM::getSubArch(ArchKind);
ArchProfile = llvm::ARM::parseArchProfile(SubArch);
ArchVersion = llvm::ARM::parseArchVersion(SubArch);
ArchMinorVersion = llvm::ARM::parseArchMinorVersion(SubArch);

// cache CPU related strings
CPUAttr = getCPUAttr();
Expand Down Expand Up @@ -737,16 +736,9 @@ void ARMTargetInfo::getTargetDefines(const LangOptions &Opts,
if (!CPUAttr.empty())
Builder.defineMacro("__ARM_ARCH_" + CPUAttr + "__");

// __ARM_ARCH is defined as an integer value indicating the current ARM ISA.
// For ISAs up to and including v8, __ARM_ARCH is equal to the major version
// number. For ISAs from v8.1 onwards, __ARM_ARCH is scaled up to include the
// minor version number, e.g. for ARM architecture ARMvX.Y:
// __ARM_ARCH = X * 100 + Y.
if (ArchVersion >= 9 || ArchMinorVersion != 0)
Builder.defineMacro("__ARM_ARCH",
Twine(ArchVersion * 100 + ArchMinorVersion));
else
Builder.defineMacro("__ARM_ARCH", Twine(ArchVersion));
// ACLE 6.4.1 ARM/Thumb instruction set architecture
// __ARM_ARCH is defined as an integer value indicating the current ARM ISA
Builder.defineMacro("__ARM_ARCH", Twine(ArchVersion));

if (ArchVersion >= 8) {
// ACLE 6.5.7 Crypto Extension
Expand Down
1 change: 0 additions & 1 deletion clang/lib/Basic/Targets/ARM.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ class LLVM_LIBRARY_VISIBILITY ARMTargetInfo : public TargetInfo {
llvm::ARM::ArchKind ArchKind = llvm::ARM::ArchKind::ARMV4T;
llvm::ARM::ProfileKind ArchProfile;
unsigned ArchVersion;
unsigned ArchMinorVersion;

LLVM_PREFERRED_TYPE(FPUMode)
unsigned FPU : 5;
Expand Down
5 changes: 1 addition & 4 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,6 @@ createTargetCodeGenInfo(CodeGenModule &CGM) {
Kind = AArch64ABIKind::DarwinPCS;
else if (Triple.isOSWindows())
return createWindowsAArch64TargetCodeGenInfo(CGM, AArch64ABIKind::Win64);
else if (Target.getABI() == "aapcs-soft")
Kind = AArch64ABIKind::AAPCSSoft;

return createAArch64TargetCodeGenInfo(CGM, Kind);
}
Expand Down Expand Up @@ -3987,8 +3985,7 @@ bool CodeGenModule::shouldEmitFunction(GlobalDecl GD) {
// behavior may break ABI compatibility of the current unit.
if (const Module *M = F->getOwningModule();
M && M->getTopLevelModule()->isNamedModule() &&
getContext().getCurrentNamedModule() != M->getTopLevelModule() &&
!F->hasAttr<AlwaysInlineAttr>())
getContext().getCurrentNamedModule() != M->getTopLevelModule())
return false;

if (F->hasAttr<NoInlineAttr>())
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/CodeGen/CoverageMappingGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1942,6 +1942,8 @@ struct CounterCoverageMappingBuilder

extendRegion(E->getTrueExpr());
OutCount = propagateCounts(TrueCount, E->getTrueExpr());
} else {
OutCount = TrueCount;
}

extendRegion(E->getFalseExpr());
Expand Down
1 change: 0 additions & 1 deletion clang/lib/CodeGen/TargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,6 @@ enum class AArch64ABIKind {
AAPCS = 0,
DarwinPCS,
Win64,
AAPCSSoft,
};

std::unique_ptr<TargetCodeGenInfo>
Expand Down
17 changes: 5 additions & 12 deletions clang/lib/CodeGen/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ class AArch64ABIInfo : public ABIInfo {
Address EmitDarwinVAArg(Address VAListAddr, QualType Ty,
CodeGenFunction &CGF) const;

Address EmitAAPCSVAArg(Address VAListAddr, QualType Ty, CodeGenFunction &CGF,
AArch64ABIKind Kind) const;
Address EmitAAPCSVAArg(Address VAListAddr, QualType Ty,
CodeGenFunction &CGF) const;

Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
QualType Ty) const override {
Expand All @@ -65,7 +65,7 @@ class AArch64ABIInfo : public ABIInfo {

return Kind == AArch64ABIKind::Win64 ? EmitMSVAArg(CGF, VAListAddr, Ty)
: isDarwinPCS() ? EmitDarwinVAArg(VAListAddr, Ty, CGF)
: EmitAAPCSVAArg(VAListAddr, Ty, CGF, Kind);
: EmitAAPCSVAArg(VAListAddr, Ty, CGF);
}

Address EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr,
Expand Down Expand Up @@ -482,11 +482,6 @@ bool AArch64SwiftABIInfo::isLegalVectorType(CharUnits VectorSize,
}

bool AArch64ABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const {
// For the soft-float ABI variant, no types are considered to be homogeneous
// aggregates.
if (Kind == AArch64ABIKind::AAPCSSoft)
return false;

// Homogeneous aggregates for AAPCS64 must have base types of a floating
// point type or a short-vector type. This is the same as the 32-bit ABI,
// but with the difference that any floating-point type is allowed,
Expand Down Expand Up @@ -518,8 +513,7 @@ bool AArch64ABIInfo::isZeroLengthBitfieldPermittedInHomogeneousAggregate()
}

Address AArch64ABIInfo::EmitAAPCSVAArg(Address VAListAddr, QualType Ty,
CodeGenFunction &CGF,
AArch64ABIKind Kind) const {
CodeGenFunction &CGF) const {
ABIArgInfo AI = classifyArgumentType(Ty, /*IsVariadic=*/true,
CGF.CurFnInfo->getCallingConvention());
// Empty records are ignored for parameter passing purposes.
Expand All @@ -544,8 +538,7 @@ Address AArch64ABIInfo::EmitAAPCSVAArg(Address VAListAddr, QualType Ty,
BaseTy = ArrTy->getElementType();
NumRegs = ArrTy->getNumElements();
}
bool IsFPR = Kind != AArch64ABIKind::AAPCSSoft &&
(BaseTy->isFloatingPointTy() || BaseTy->isVectorTy());
bool IsFPR = BaseTy->isFloatingPointTy() || BaseTy->isVectorTy();

// The AArch64 va_list type and handling is specified in the Procedure Call
// Standard, section B.4:
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Format/QualifierAlignmentFixer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,8 @@ void LeftRightQualifierAlignmentFixer::fixQualifierAlignment(

for (const auto *Tok = First; Tok && Tok != Last && Tok->Next;
Tok = Tok->Next) {
if (Tok->MustBreakBefore)
break;
if (Tok->is(tok::comment))
continue;
if (RightAlign) {
Expand Down
20 changes: 10 additions & 10 deletions clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3754,10 +3754,11 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
for (AnnotatedLine *ChildLine : Line.Children)
calculateFormattingInformation(*ChildLine);

Line.First->TotalLength =
Line.First->IsMultiline ? Style.ColumnLimit
: Line.FirstStartColumn + Line.First->ColumnWidth;
FormatToken *Current = Line.First->Next;
auto *First = Line.First;
First->TotalLength = First->IsMultiline
? Style.ColumnLimit
: Line.FirstStartColumn + First->ColumnWidth;
FormatToken *Current = First->Next;
bool InFunctionDecl = Line.MightBeFunctionDecl;
bool AlignArrayOfStructures =
(Style.AlignArrayOfStructures != FormatStyle::AIAS_None &&
Expand All @@ -3779,16 +3780,15 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
if (const bool IsCtorOrDtor = Tok->is(TT_CtorDtorDeclName);
IsCtorOrDtor ||
isFunctionDeclarationName(Style.isCpp(), *Tok, Line, ClosingParen)) {
if (!IsCtorOrDtor) {
LineIsFunctionDeclaration = true;
if (!IsCtorOrDtor)
Tok->setFinalizedType(TT_FunctionDeclarationName);
}
LineIsFunctionDeclaration = true;
SeenName = true;
break;
}
}

if (IsCpp && LineIsFunctionDeclaration &&
if (IsCpp && (LineIsFunctionDeclaration || First->is(TT_CtorDtorDeclName)) &&
Line.endsWith(tok::semi, tok::r_brace)) {
auto *Tok = Line.Last->Previous;
while (Tok->isNot(tok::r_brace))
Expand All @@ -3811,7 +3811,7 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
if (IsCpp) {
if (!LineIsFunctionDeclaration) {
// Annotate */&/&& in `operator` function calls as binary operators.
for (const auto *Tok = Line.First; Tok; Tok = Tok->Next) {
for (const auto *Tok = First; Tok; Tok = Tok->Next) {
if (Tok->isNot(tok::kw_operator))
continue;
do {
Expand Down Expand Up @@ -3948,7 +3948,7 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {

calculateUnbreakableTailLengths(Line);
unsigned IndentLevel = Line.Level;
for (Current = Line.First; Current; Current = Current->Next) {
for (Current = First; Current; Current = Current->Next) {
if (Current->Role)
Current->Role->precomputeFormattingInfos(Current);
if (Current->MatchingParen &&
Expand Down
20 changes: 7 additions & 13 deletions clang/lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ static bool attributeHasIdentifierArg(const IdentifierInfo &II) {

/// Determine whether the given attribute has an identifier argument.
static ParsedAttributeArgumentsProperties
attributeStringLiteralListArg(const IdentifierInfo &II) {
attributeStringLiteralListArg(const llvm::Triple &T, const IdentifierInfo &II) {
#define CLANG_ATTR_STRING_LITERAL_ARG_LIST
return llvm::StringSwitch<uint32_t>(normalizeAttrName(II.getName()))
#include "clang/Parse/AttrParserStringSwitches.inc"
Expand Down Expand Up @@ -550,7 +550,7 @@ unsigned Parser::ParseAttributeArgsCommon(

ExprVector ParsedExprs;
ParsedAttributeArgumentsProperties ArgProperties =
attributeStringLiteralListArg(*AttrName);
attributeStringLiteralListArg(getTargetInfo().getTriple(), *AttrName);
if (ParseAttributeArgumentList(*AttrName, ParsedExprs, ArgProperties)) {
SkipUntil(tok::r_paren, StopAtSemi);
return 0;
Expand Down Expand Up @@ -3520,8 +3520,7 @@ void Parser::ParseDeclarationSpecifiers(

// alignment-specifier
case tok::kw__Alignas:
if (!getLangOpts().C11)
Diag(Tok, diag::ext_c11_feature) << Tok.getName();
diagnoseUseOfC11Keyword(Tok);
[[fallthrough]];
case tok::kw_alignas:
// _Alignas and alignas (C23, not C++) should parse the same way. The C++
Expand Down Expand Up @@ -4184,8 +4183,7 @@ void Parser::ParseDeclarationSpecifiers(
isStorageClass = true;
break;
case tok::kw__Thread_local:
if (!getLangOpts().C11)
Diag(Tok, diag::ext_c11_feature) << Tok.getName();
diagnoseUseOfC11Keyword(Tok);
isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS__Thread_local,
Loc, PrevSpec, DiagID);
isStorageClass = true;
Expand Down Expand Up @@ -4245,8 +4243,7 @@ void Parser::ParseDeclarationSpecifiers(
break;
}
case tok::kw__Noreturn:
if (!getLangOpts().C11)
Diag(Tok, diag::ext_c11_feature) << Tok.getName();
diagnoseUseOfC11Keyword(Tok);
isInvalid = DS.setFunctionSpecNoreturn(Loc, PrevSpec, DiagID);
break;

Expand Down Expand Up @@ -4576,9 +4573,7 @@ void Parser::ParseDeclarationSpecifiers(
// If the _Atomic keyword is immediately followed by a left parenthesis,
// it is interpreted as a type specifier (with a type name), not as a
// type qualifier.
if (!getLangOpts().C11)
Diag(Tok, diag::ext_c11_feature) << Tok.getName();

diagnoseUseOfC11Keyword(Tok);
if (NextToken().is(tok::l_paren)) {
ParseAtomicSpecifier(DS);
continue;
Expand Down Expand Up @@ -6154,8 +6149,7 @@ void Parser::ParseTypeQualifierListOpt(
case tok::kw__Atomic:
if (!AtomicAllowed)
goto DoneWithTypeQuals;
if (!getLangOpts().C11)
Diag(Tok, diag::ext_c11_feature) << Tok.getName();
diagnoseUseOfC11Keyword(Tok);
isInvalid = DS.SetTypeQual(DeclSpec::TQ_atomic, Loc, PrevSpec, DiagID,
getLangOpts());
break;
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/Parse/ParseDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -968,9 +968,9 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd) {
// Save the token name used for static assertion.
const char *TokName = Tok.getName();

if (Tok.is(tok::kw__Static_assert) && !getLangOpts().C11)
Diag(Tok, diag::ext_c11_feature) << Tok.getName();
if (Tok.is(tok::kw_static_assert)) {
if (Tok.is(tok::kw__Static_assert))
diagnoseUseOfC11Keyword(Tok);
else if (Tok.is(tok::kw_static_assert)) {
if (!getLangOpts().CPlusPlus) {
if (getLangOpts().C23)
Diag(Tok, diag::warn_c23_compat_keyword) << Tok.getName();
Expand Down
7 changes: 3 additions & 4 deletions clang/lib/Parse/ParseExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1462,8 +1462,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
return Res;
}
case tok::kw__Alignof: // unary-expression: '_Alignof' '(' type-name ')'
if (!getLangOpts().C11)
Diag(Tok, diag::ext_c11_feature) << Tok.getName();
diagnoseUseOfC11Keyword(Tok);
[[fallthrough]];
case tok::kw_alignof: // unary-expression: 'alignof' '(' type-id ')'
case tok::kw___alignof: // unary-expression: '__alignof' unary-expression
Expand Down Expand Up @@ -3389,8 +3388,8 @@ ExprResult Parser::ParseStringLiteralExpression(bool AllowUserDefinedLiteral,
/// \endverbatim
ExprResult Parser::ParseGenericSelectionExpression() {
assert(Tok.is(tok::kw__Generic) && "_Generic keyword expected");
if (!getLangOpts().C11)
Diag(Tok, diag::ext_c11_feature) << Tok.getName();

diagnoseUseOfC11Keyword(Tok);

SourceLocation KeyLoc = ConsumeToken();
BalancedDelimiterTracker T(*this, tok::l_paren);
Expand Down
9 changes: 9 additions & 0 deletions clang/lib/Parse/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2742,6 +2742,15 @@ bool Parser::parseMisplacedModuleImport() {
return false;
}

void Parser::diagnoseUseOfC11Keyword(const Token &Tok) {
// Warn that this is a C11 extension if in an older mode or if in C++.
// Otherwise, warn that it is incompatible with standards before C11 if in
// C11 or later.
Diag(Tok, getLangOpts().C11 ? diag::warn_c11_compat_keyword
: diag::ext_c11_feature)
<< Tok.getName();
}

bool BalancedDelimiterTracker::diagnoseOverflow() {
P.Diag(P.Tok, diag::err_bracket_depth_exceeded)
<< P.getLangOpts().BracketDepth;
Expand Down
34 changes: 0 additions & 34 deletions clang/lib/Sema/Sema.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1944,21 +1944,6 @@ Sema::SemaDiagnosticBuilder Sema::Diag(SourceLocation Loc, unsigned DiagID,
return DB;
}

static bool typeIsOrContainsFloat(const Type &Ty) {
if (Ty.isFloatingType())
return true;

if (const RecordDecl *Decl = Ty.getAsRecordDecl()) {
for (const FieldDecl *FD : Decl->fields()) {
const Type &FieldType = *FD->getType();
if (typeIsOrContainsFloat(FieldType))
return true;
}
}

return false;
}

void Sema::checkTypeSupport(QualType Ty, SourceLocation Loc, ValueDecl *D) {
if (isUnevaluatedContext() || Ty.isNull())
return;
Expand Down Expand Up @@ -2103,25 +2088,6 @@ void Sema::checkTypeSupport(QualType Ty, SourceLocation Loc, ValueDecl *D) {
!Builtin::evaluateRequiredTargetFeatures("sme", CallerFeatureMap))
Diag(D->getLocation(), diag::err_sve_vector_in_non_sve_target) << Ty;
}

// Don't allow any floating-point types (including structs containing
// floats) for ABIs which do not support them.
if (!TI.hasFPTypes() && typeIsOrContainsFloat(*UnqualTy)) {
PartialDiagnostic PD = PDiag(diag::err_target_unsupported_type_for_abi);

if (D)
PD << D;
else
PD << "expression";

if (Diag(Loc, PD, FD) << Ty << TI.getABI()) {
if (D)
D->setInvalidDecl();
}

if (D)
targetDiag(D->getLocation(), diag::note_defined_here, FD) << D;
}
};

CheckType(Ty);
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6201,6 +6201,12 @@ struct ImmediateCallVisitor : public RecursiveASTVisitor<ImmediateCallVisitor> {
return RecursiveASTVisitor<ImmediateCallVisitor>::VisitStmt(E);
}

bool VisitCXXConstructExpr(CXXConstructExpr *E) {
if (const FunctionDecl *FD = E->getConstructor())
HasImmediateCalls |= FD->isImmediateFunction();
return RecursiveASTVisitor<ImmediateCallVisitor>::VisitStmt(E);
}

// SourceLocExpr are not immediate invocations
// but CXXDefaultInitExpr/CXXDefaultArgExpr containing a SourceLocExpr
// need to be rebuilt so that they refer to the correct SourceLocation and
Expand Down
19 changes: 19 additions & 0 deletions clang/test/AST/Interp/arrays.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -545,3 +545,22 @@ namespace LocalIndex {
array[const_subscript] = 0; // both-warning {{array index 3 is past the end of the array (that has type 'int[2]')}}
}
}

namespace LocalVLA {
struct Foo {
int x;
Foo(int x) : x(x) {}
};
struct Elidable {
Elidable();
};

void foo(int size) {
Elidable elidableDynArray[size];
#if __cplusplus >= 202002L
// both-note@-3 {{declared here}}
// both-warning@-3 {{variable length array}}
// both-note@-4 {{function parameter 'size' with unknown value}}
#endif
}
}
10 changes: 10 additions & 0 deletions clang/test/AST/Interp/comma.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// RUN: %clang_cc1 -fsyntax-only -verify %s -fexperimental-new-constant-interpreter
// expected-no-diagnostics

// PR6076
void f();
void (&g)() = (void(), f);

int a[1];
int (&b)[1] = (void(), a);
13 changes: 13 additions & 0 deletions clang/test/AST/Interp/crash-GH49103-2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// RUN: %clang_cc1 -verify -std=c++98 %s -fexperimental-new-constant-interpreter
// RUN: %clang_cc1 -verify -std=c++11 %s -fexperimental-new-constant-interpreter
// RUN: %clang_cc1 -verify -std=c++14 %s -fexperimental-new-constant-interpreter
// RUN: %clang_cc1 -verify -std=c++17 %s -fexperimental-new-constant-interpreter
// RUN: %clang_cc1 -verify -std=c++20 %s -fexperimental-new-constant-interpreter
// RUN: %clang_cc1 -verify -std=c++23 %s -fexperimental-new-constant-interpreter
// RUN: %clang_cc1 -verify -std=c++2c %s -fexperimental-new-constant-interpreter

// https://github.com/llvm/llvm-project/issues/49103

template<class> struct A; // expected-note 0+ {{}}
struct S : __make_integer_seq<A, int, 42> { }; // expected-error 0+ {{}}
S s;
12 changes: 12 additions & 0 deletions clang/test/AST/Interp/cxx03.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// RUN: %clang_cc1 -std=c++03 -verify=expected,both %s -fexperimental-new-constant-interpreter
// RUN: %clang_cc1 -std=c++03 -verify=ref,both %s

namespace NonInitializingMemberExpr {
struct NonLit {
NonLit() : value(0) {}
int value;
};
__attribute__((require_constant_initialization)) const int &nl_subobj_ref = NonLit().value; // both-error {{variable does not have a constant initializer}} \
// both-note {{required by}} \
// both-note {{subexpression not valid}}
}
13 changes: 13 additions & 0 deletions clang/test/AST/Interp/cxx20.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -763,3 +763,16 @@ namespace IgnoredConstantExpr {
ReferenceToNestedMembers j{0};
} test_reference_to_nested_members;
}

namespace RewrittenBinaryOperators {
template <class T, T Val>
struct Conv {
constexpr operator T() const { return Val; }
operator T() { return Val; }
};

struct X {
constexpr const Conv<int, -1> operator<=>(X) { return {}; }
};
static_assert(X() < X(), "");
}
29 changes: 25 additions & 4 deletions clang/test/AST/Interp/cxx23.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=ref20 %s
// RUN: %clang_cc1 -std=c++23 -fsyntax-only -fcxx-exceptions -verify=ref23 %s
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=expected20 %s -fexperimental-new-constant-interpreter
// RUN: %clang_cc1 -std=c++23 -fsyntax-only -fcxx-exceptions -verify=expected23 %s -fexperimental-new-constant-interpreter
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=ref20,all %s
// RUN: %clang_cc1 -std=c++23 -fsyntax-only -fcxx-exceptions -verify=ref23,all %s
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=expected20,all %s -fexperimental-new-constant-interpreter
// RUN: %clang_cc1 -std=c++23 -fsyntax-only -fcxx-exceptions -verify=expected23,all %s -fexperimental-new-constant-interpreter

/// FIXME: The new interpreter is missing all the 'control flows through...' diagnostics.

Expand Down Expand Up @@ -123,3 +123,24 @@ namespace StaticLambdas {
}
static_assert(capture_constexpr());
}

namespace StaticOperators {
auto lstatic = []() static { return 3; }; // ref20-warning {{C++23 extension}} \
// expected20-warning {{C++23 extension}}
static_assert(lstatic() == 3, "");
constexpr int (*f2)(void) = lstatic;
static_assert(f2() == 3);

struct S1 {
constexpr S1() { // all-error {{never produces a constant expression}}
throw; // all-note 2{{not valid in a constant expression}}
}
static constexpr int operator()() { return 3; } // ref20-warning {{C++23 extension}} \
// expected20-warning {{C++23 extension}}
};
static_assert(S1{}() == 3, ""); // all-error {{not an integral constant expression}} \
// all-note {{in call to}}



}
9 changes: 9 additions & 0 deletions clang/test/AST/Interp/functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -543,3 +543,12 @@ namespace StaticLocals {
static_assert(m == 0, "");
}
}

namespace Local {
/// We used to run into infinite recursin here because we were
/// trying to evaluate t's initializer while evaluating t's initializer.
int a() {
const int t=t;
return t;
}
}
13 changes: 13 additions & 0 deletions clang/test/AST/Interp/lambda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,3 +222,16 @@ namespace GH62611 {
return 0;
}
}

namespace LambdaToAPValue {
void wrapper() {
constexpr auto f = []() constexpr {
return 0;
};

constexpr auto g = [f]() constexpr {
return f();
};
static_assert(g() == f(), "");
}
}
7 changes: 7 additions & 0 deletions clang/test/AST/Interp/literals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1124,3 +1124,10 @@ namespace rdar8769025 {
f1(0); // both-warning{{null passed to a callee that requires a non-null argument}}
}
}

namespace nullptrsub {
void a() {
char *f = (char *)0;
f = (char *)((char *)0 - (char *)0);
}
}
12 changes: 6 additions & 6 deletions clang/test/AST/Interp/records.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,9 +335,9 @@ namespace InitializerTemporaries {
};

constexpr int f() {
S{}; // ref-note {{in call to 'S{}.~S()'}}
/// FIXME: Wrong source location below.
return 12; // expected-note {{in call to '&S{}->~S()'}}
S{}; // ref-note {{in call to 'S{}.~S()'}} \
// expected-note {{in call to '&S{}->~S()'}}
return 12;
}
static_assert(f() == 12); // both-error {{not an integral constant expression}} \
// both-note {{in call to 'f()'}}
Expand Down Expand Up @@ -604,9 +604,9 @@ namespace Destructors {
}
};
constexpr int testS() {
S{}; // ref-note {{in call to 'S{}.~S()'}}
return 1; // expected-note {{in call to '&S{}->~S()'}}
// FIXME: ^ Wrong line
S{}; // ref-note {{in call to 'S{}.~S()'}} \
// expected-note {{in call to '&S{}->~S()'}}
return 1;
}
static_assert(testS() == 1); // both-error {{not an integral constant expression}} \
// both-note {{in call to 'testS()'}}
Expand Down
9 changes: 9 additions & 0 deletions clang/test/AST/Interp/shifts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,3 +188,12 @@ namespace shifts {
// ref-cxx17-error {{not an integral constant expression}} \
// ref-cxx17-note {{in call to 'foo(2)'}}
};

namespace LongInt {
constexpr int f() {
int a = 1;
a <<= (long)0;
return 1;
}
static_assert(f() == 1, "");
};
56 changes: 0 additions & 56 deletions clang/test/CodeGen/aarch64-soft-float-abi.c

This file was deleted.

36 changes: 18 additions & 18 deletions clang/test/CodeGen/attr-target-clones-aarch64.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-attributes --check-globals --include-generated-funcs
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature -fp-armv8 -S -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature -fp-armv8 -target-feature -fmv -S -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-NOFMV
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -S -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature -fmv -S -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-NOFMV

int __attribute__((target_clones("lse+aes", "sve2"))) ftc(void) { return 0; }
int __attribute__((target_clones("sha2", "sha2+memtag2", " default "))) ftc_def(void) { return 1; }
Expand Down Expand Up @@ -414,23 +414,23 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default"))
// CHECK-NOFMV-NEXT: ret i32 [[ADD5]]
//
//.
// CHECK: attributes #[[ATTR0:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+lse,+neon,-fp-armv8" }
// CHECK: attributes #[[ATTR1:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+neon,+sve,+sve2,-fp-armv8" }
// CHECK: attributes #[[ATTR2:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fp-armv8" }
// CHECK: attributes #[[ATTR3:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon,+sha2,-fp-armv8" }
// CHECK: attributes #[[ATTR4:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+mte,+neon,+sha2,-fp-armv8" }
// CHECK: attributes #[[ATTR5:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon,-fp-armv8" }
// CHECK: attributes #[[ATTR6:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc,+dotprod,+neon,-fp-armv8" }
// CHECK: attributes #[[ATTR7:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon,+rand,-fp-armv8" }
// CHECK: attributes #[[ATTR8:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+predres,+rcpc,-fp-armv8" }
// CHECK: attributes #[[ATTR9:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+neon,+sve,+sve2,+sve2-aes,+wfxt,-fp-armv8" }
// CHECK: attributes #[[ATTR10:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+neon,-fp-armv8" }
// CHECK: attributes #[[ATTR11:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+complxnum,+fullfp16,+neon,+sve,+sve2,+sve2-bitperm,-fp-armv8" }
// CHECK: attributes #[[ATTR12:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bti,-fp-armv8" }
// CHECK: attributes #[[ATTR13:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+neon,+sb,+sve,-fp-armv8" }
// CHECK: attributes #[[ATTR0:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+lse,+neon" }
// CHECK: attributes #[[ATTR1:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve,+sve2" }
// CHECK: attributes #[[ATTR2:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
// CHECK: attributes #[[ATTR3:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+sha2" }
// CHECK: attributes #[[ATTR4:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+mte,+neon,+sha2" }
// CHECK: attributes #[[ATTR5:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon" }
// CHECK: attributes #[[ATTR6:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc,+dotprod,+fp-armv8,+neon" }
// CHECK: attributes #[[ATTR7:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+rand" }
// CHECK: attributes #[[ATTR8:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+predres,+rcpc" }
// CHECK: attributes #[[ATTR9:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve,+sve2,+sve2-aes,+wfxt" }
// CHECK: attributes #[[ATTR10:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon" }
// CHECK: attributes #[[ATTR11:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+complxnum,+fp-armv8,+fullfp16,+neon,+sve,+sve2,+sve2-bitperm" }
// CHECK: attributes #[[ATTR12:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bti" }
// CHECK: attributes #[[ATTR13:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sb,+sve" }
//.
// CHECK-NOFMV: attributes #[[ATTR0:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fmv,-fp-armv8" }
// CHECK-NOFMV: attributes #[[ATTR1:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fmv,-fp-armv8" }
// CHECK-NOFMV: attributes #[[ATTR0:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fmv" }
// CHECK-NOFMV: attributes #[[ATTR1:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fmv" }
//.
// CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
// CHECK: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}
Expand Down
17 changes: 17 additions & 0 deletions clang/test/CodeGenCXX/cxx2a-consteval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,3 +258,20 @@ void void_call() { // EVAL-FN-LABEL: define {{.*}} @_Z9void_call
void_test();
// EVAL-FN: {{^}}}
}


namespace GH82154 {
struct S1 { consteval S1(int) {} };
struct S3 { constexpr S3(int) {} };

void f() {
struct S2 {
S1 s = 0;
S3 s2 = 0;
};
S2 s;
// EVAL-FN-LABEL: define {{.*}} void @_ZZN7GH821541fEvEN2S2C2Ev
// EVAL-FN-NOT: call void @_ZN7GH821542S1C2Ei
// EVAL-FN: call void @_ZN7GH821542S3C2Ei
}
}
6 changes: 3 additions & 3 deletions clang/test/CodeGenCXX/module-funcs-from-imports.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@ int use() {
return exported_func() + always_inline_func();
}

// Checks that none of the function (except the always_inline_func) in the importees
// Checks that none of the function in the importees
// are generated in the importer's code.
// CHECK-O0: define{{.*}}_Z3usev(
// CHECK-O0: declare{{.*}}_ZW1M13exported_funcv(
// CHECK-O0: define{{.*}}available_externally{{.*}}_ZW1M18always_inline_funcv(
// CHECK-O0: declare{{.*}}_ZW1M18always_inline_funcv(
// CHECK-O0-NOT: func_in_gmf
// CHECK-O0-NOT: func_in_gmf_not_called
// CHECK-O0-NOT: non_exported_func
Expand All @@ -68,7 +68,7 @@ int use() {
// O0 to keep consistent ABI.
// CHECK-O1: define{{.*}}_Z3usev(
// CHECK-O1: declare{{.*}}_ZW1M13exported_funcv(
// CHECK-O1: define{{.*}}available_externally{{.*}}_ZW1M18always_inline_funcv(
// CHECK-O1: declare{{.*}}_ZW1M18always_inline_funcv(
// CHECK-O1-NOT: func_in_gmf
// CHECK-O1-NOT: func_in_gmf_not_called
// CHECK-O1-NOT: non_exported_func
Expand Down
5 changes: 4 additions & 1 deletion clang/test/CodeGenOpenCL/builtins-amdgcn-dl-insts-gfx11.cl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ typedef unsigned short __attribute__((ext_vector_type(2))) ushort2;
// CHECK: call float @llvm.amdgcn.fdot2(<2 x half> %v2hA, <2 x half> %v2hB, float %fC, i1 false)
// CHECK: call float @llvm.amdgcn.fdot2(<2 x half> %v2hA, <2 x half> %v2hB, float %fC, i1 true)
// CHECK: call half @llvm.amdgcn.fdot2.f16.f16(<2 x half> %v2hA, <2 x half> %v2hB, half %hC)
// CHECK: call i16 @llvm.amdgcn.fdot2.bf16.bf16(<2 x i16> %v2ssA, <2 x i16> %v2ssB, i16 %sC)
// CHECK: [[s1:%[0-9]+]] = bitcast <2 x i16> %v2ssA to <2 x bfloat>
// CHECK-NEXT: [[s2:%[0-9]+]] = bitcast <2 x i16> %v2ssB to <2 x bfloat>
// CHECK-NEXT: [[s3:%[0-9]+]] = bitcast i16 %sC to bfloat
// CHECK-NEXT: [[d:%[0-9]+]] = tail call bfloat @llvm.amdgcn.fdot2.bf16.bf16(<2 x bfloat> [[s1]], <2 x bfloat> [[s2]], bfloat [[s3]])
// CHECK: call float @llvm.amdgcn.fdot2.f32.bf16(<2 x i16> %v2ssA, <2 x i16> %v2ssB, float %fC, i1 false)
// CHECK: call float @llvm.amdgcn.fdot2.f32.bf16(<2 x i16> %v2ssA, <2 x i16> %v2ssB, float %fC, i1 true)
// CHECK: call i32 @llvm.amdgcn.udot4(i32 %uiA, i32 %uiB, i32 %uiC, i1 false)
Expand Down
25 changes: 25 additions & 0 deletions clang/test/CoverageMapping/conditional-operator.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// RUN: %clang_cc1 -mllvm -emptyline-comment-coverage=false -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only %s | FileCheck %s

// CHECK-LABEL: binary_conditional:
// CHECK-NEXT: File 0, [[@LINE+4]]:31 -> {{[0-9]+}}:2 = #0
// CHECK-NEXT: File 0, [[@LINE+4]]:7 -> [[@LINE+4]]:8 = #0
// CHECK-NEXT: Branch,File 0, [[@LINE+3]]:7 -> [[@LINE+3]]:8 = #1, (#0 - #1)
// CHECK-NEXT: File 0, [[@LINE+2]]:13 -> [[@LINE+2]]:14 = (#0 - #1)
int binary_conditional(int x) {
x = x ? : 4;
int y = x;
return y;
}

// CHECK-LABEL: ternary_conditional:
// CHECK-NEXT: File 0, [[@LINE+6]]:32 -> {{[0-9]+}}:2 = #0
// CHECK-NEXT: File 0, [[@LINE+6]]:7 -> [[@LINE+6]]:8 = #0
// CHECK-NEXT: Branch,File 0, [[@LINE+5]]:7 -> [[@LINE+5]]:8 = #1, (#0 - #1)
// CHECK-NEXT: Gap,File 0, [[@LINE+4]]:10 -> [[@LINE+4]]:11 = #1
// CHECK-NEXT: File 0, [[@LINE+3]]:11 -> [[@LINE+3]]:12 = #1
// CHECK-NEXT: File 0, [[@LINE+2]]:15 -> [[@LINE+2]]:16 = (#0 - #1)
int ternary_conditional(int x) {
x = x ? x : 4;
int y = x;
return y;
}
25 changes: 0 additions & 25 deletions clang/test/Driver/aarch64-soft-float-abi.c

This file was deleted.

37 changes: 37 additions & 0 deletions clang/test/Parser/c11-keywords.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// RUN: %clang_cc1 %s -std=c11 -fsyntax-only -verify=compat -Wpre-c11-compat
// RUN: %clang_cc1 %s -std=c99 -fsyntax-only -verify=ext -pedantic
// RUN: %clang_cc1 %s -std=c11 -fsyntax-only -verify=good
// RUN: %clang_cc1 -x c++ %s -fsyntax-only -verify=ext -pedantic

// good-no-diagnostics

extern _Noreturn void exit(int); /* compat-warning {{'_Noreturn' is incompatible with C standards before C11}}
ext-warning {{'_Noreturn' is a C11 extension}}
*/

void func(void) {
static _Thread_local int tl; /* compat-warning {{'_Thread_local' is incompatible with C standards before C11}}
ext-warning {{'_Thread_local' is a C11 extension}}
*/
_Alignas(8) char c; /* compat-warning {{'_Alignas' is incompatible with C standards before C11}}
ext-warning {{'_Alignas' is a C11 extension}}
*/
_Atomic int i1; /* compat-warning {{'_Atomic' is incompatible with C standards before C11}}
ext-warning {{'_Atomic' is a C11 extension}}
*/
_Atomic(int) i2; /* compat-warning {{'_Atomic' is incompatible with C standards before C11}}
ext-warning {{'_Atomic' is a C11 extension}}
*/

_Static_assert(1, ""); /* compat-warning {{'_Static_assert' is incompatible with C standards before C11}}
ext-warning {{'_Static_assert' is a C11 extension}}
*/

(void)_Generic(1, int : 1); /* compat-warning {{'_Generic' is incompatible with C standards before C11}}
ext-warning {{'_Generic' is a C11 extension}}
*/
(void)_Alignof(int); /* compat-warning {{'_Alignof' is incompatible with C standards before C11}}
ext-warning {{'_Alignof' is a C11 extension}}
*/
}

6 changes: 3 additions & 3 deletions clang/test/Preprocessor/aarch64-target-features.c
Original file line number Diff line number Diff line change
Expand Up @@ -342,15 +342,15 @@

// RUN: %clang -target aarch64 -march=armv8-a+fp+simd+crc+crypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MARCH-1 %s
// RUN: %clang -target aarch64 -march=armv8-a+nofp+nosimd+nocrc+nocrypto+fp+simd+crc+crypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MARCH-1 %s
// RUN: %clang -target aarch64 -march=armv8-a+nofp+nosimd+nocrc+nocrypto -mabi=aapcs-soft -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MARCH-2 %s
// RUN: %clang -target aarch64 -march=armv8-a+fp+simd+crc+crypto+nofp+nosimd+nocrc+nocrypto -mabi=aapcs-soft -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MARCH-2 %s
// RUN: %clang -target aarch64 -march=armv8-a+nofp+nosimd+nocrc+nocrypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MARCH-2 %s
// RUN: %clang -target aarch64 -march=armv8-a+fp+simd+crc+crypto+nofp+nosimd+nocrc+nocrypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MARCH-2 %s
// RUN: %clang -target aarch64 -march=armv8-a+nosimd -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MARCH-3 %s
// CHECK-MARCH-1: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8a" "-target-feature" "+aes" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+fp-armv8" "-target-feature" "+sha2" "-target-feature" "+neon"
// CHECK-MARCH-2: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "-fp-armv8"{{.*}} "-target-feature" "-neon"
// CHECK-MARCH-3: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "-neon"

// While we're checking +nofp, also make sure it stops defining __ARM_FP
// RUN: %clang -target aarch64-none-linux-gnu -march=armv8-r+nofp -mabi=aapcs-soft -x c -E -dM %s -o - | FileCheck -check-prefix=CHECK-NOFP %s
// RUN: %clang -target aarch64-none-linux-gnu -march=armv8-r+nofp -x c -E -dM %s -o - | FileCheck -check-prefix=CHECK-NOFP %s
// CHECK-NOFP-NOT: #define __ARM_FP{{ }}

// Check +sm4:
Expand Down
34 changes: 17 additions & 17 deletions clang/test/Preprocessor/arm-target-features.c
Original file line number Diff line number Diff line change
Expand Up @@ -737,7 +737,7 @@

// Test whether predefines are as expected when targeting cortex-m55 (softfp FP ABI as default).
// RUN: %clang -target arm-eabi -mcpu=cortex-m55 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=M55 %s
// M55: #define __ARM_ARCH 801
// M55: #define __ARM_ARCH 8
// M55: #define __ARM_ARCH_8_1M_MAIN__ 1
// M55: #define __ARM_ARCH_EXT_IDIV__ 1
// M55-NOT: __ARM_ARCH_ISA_ARM
Expand All @@ -764,7 +764,7 @@
// KRAIT-ALLOW-FP-INSTR:#define __ARM_VFPV4__ 1

// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V81M %s
// CHECK-V81M: #define __ARM_ARCH 801
// CHECK-V81M: #define __ARM_ARCH 8
// CHECK-V81M: #define __ARM_ARCH_8_1M_MAIN__ 1
// CHECK-V81M: #define __ARM_ARCH_ISA_THUMB 2
// CHECK-V81M: #define __ARM_ARCH_PROFILE 'M'
Expand Down Expand Up @@ -821,14 +821,14 @@
// CHECK-V8M-CDE-MASK2: #define __ARM_FEATURE_CDE_COPROC 0xff

// RUN: %clang -target armv8.1a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V81A %s
// CHECK-V81A: #define __ARM_ARCH 801
// CHECK-V81A: #define __ARM_ARCH 8
// CHECK-V81A: #define __ARM_ARCH_8_1A__ 1
// CHECK-V81A: #define __ARM_ARCH_PROFILE 'A'
// CHECK-V81A: #define __ARM_FEATURE_QRDMX 1
// CHECK-V81A: #define __ARM_FP 0xe

// RUN: %clang -target armv8.2a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V82A %s
// CHECK-V82A: #define __ARM_ARCH 802
// CHECK-V82A: #define __ARM_ARCH 8
// CHECK-V82A: #define __ARM_ARCH_8_2A__ 1
// CHECK-V82A: #define __ARM_ARCH_PROFILE 'A'
// CHECK-V82A: #define __ARM_FEATURE_QRDMX 1
Expand All @@ -838,67 +838,67 @@
// CHECK-DRIVERKIT-NOT: #define __ARM_PCS_VFP 1

// RUN: %clang -target armv8.3a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V83A %s
// CHECK-V83A: #define __ARM_ARCH 803
// CHECK-V83A: #define __ARM_ARCH 8
// CHECK-V83A: #define __ARM_ARCH_8_3A__ 1
// CHECK-V83A: #define __ARM_ARCH_PROFILE 'A'

// RUN: %clang -target armv8.4a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V84A %s
// CHECK-V84A: #define __ARM_ARCH 804
// CHECK-V84A: #define __ARM_ARCH 8
// CHECK-V84A: #define __ARM_ARCH_8_4A__ 1
// CHECK-V84A: #define __ARM_ARCH_PROFILE 'A'

// RUN: %clang -target armv8.5a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V85A %s
// CHECK-V85A: #define __ARM_ARCH 805
// CHECK-V85A: #define __ARM_ARCH 8
// CHECK-V85A: #define __ARM_ARCH_8_5A__ 1
// CHECK-V85A: #define __ARM_ARCH_PROFILE 'A'

// RUN: %clang -target armv8.6a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V86A %s
// CHECK-V86A: #define __ARM_ARCH 806
// CHECK-V86A: #define __ARM_ARCH 8
// CHECK-V86A: #define __ARM_ARCH_8_6A__ 1
// CHECK-V86A: #define __ARM_ARCH_PROFILE 'A'

// RUN: %clang -target armv8.7a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V87A %s
// CHECK-V87A: #define __ARM_ARCH 807
// CHECK-V87A: #define __ARM_ARCH 8
// CHECK-V87A: #define __ARM_ARCH_8_7A__ 1
// CHECK-V87A: #define __ARM_ARCH_PROFILE 'A'

// RUN: %clang -target armv8.8a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V88A %s
// CHECK-V88A: #define __ARM_ARCH 808
// CHECK-V88A: #define __ARM_ARCH 8
// CHECK-V88A: #define __ARM_ARCH_8_8A__ 1
// CHECK-V88A: #define __ARM_ARCH_PROFILE 'A'

// RUN: %clang -target armv8.9a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V89A %s
// CHECK-V89A: #define __ARM_ARCH 809
// CHECK-V89A: #define __ARM_ARCH 8
// CHECK-V89A: #define __ARM_ARCH_8_9A__ 1
// CHECK-V89A: #define __ARM_ARCH_PROFILE 'A'

// RUN: %clang -target armv9a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V9A %s
// CHECK-V9A: #define __ARM_ARCH 900
// CHECK-V9A: #define __ARM_ARCH 9
// CHECK-V9A: #define __ARM_ARCH_9A__ 1
// CHECK-V9A: #define __ARM_ARCH_PROFILE 'A'

// RUN: %clang -target armv9.1a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V91A %s
// CHECK-V91A: #define __ARM_ARCH 901
// CHECK-V91A: #define __ARM_ARCH 9
// CHECK-V91A: #define __ARM_ARCH_9_1A__ 1
// CHECK-V91A: #define __ARM_ARCH_PROFILE 'A'

// RUN: %clang -target armv9.2a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V92A %s
// CHECK-V92A: #define __ARM_ARCH 902
// CHECK-V92A: #define __ARM_ARCH 9
// CHECK-V92A: #define __ARM_ARCH_9_2A__ 1
// CHECK-V92A: #define __ARM_ARCH_PROFILE 'A'

// RUN: %clang -target armv9.3a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V93A %s
// CHECK-V93A: #define __ARM_ARCH 903
// CHECK-V93A: #define __ARM_ARCH 9
// CHECK-V93A: #define __ARM_ARCH_9_3A__ 1
// CHECK-V93A: #define __ARM_ARCH_PROFILE 'A'

// RUN: %clang -target armv9.4a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V94A %s
// CHECK-V94A: #define __ARM_ARCH 904
// CHECK-V94A: #define __ARM_ARCH 9
// CHECK-V94A: #define __ARM_ARCH_9_4A__ 1
// CHECK-V94A: #define __ARM_ARCH_PROFILE 'A'

// RUN: %clang -target armv9.5a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V95A %s
// CHECK-V95A: #define __ARM_ARCH 905
// CHECK-V95A: #define __ARM_ARCH 9
// CHECK-V95A: #define __ARM_ARCH_9_5A__ 1
// CHECK-V95A: #define __ARM_ARCH_PROFILE 'A'

Expand Down
54 changes: 0 additions & 54 deletions clang/test/Sema/aarch64-soft-float-abi.c

This file was deleted.

2 changes: 1 addition & 1 deletion clang/test/Sema/attr-function-return.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ __attribute__((function_return("thunk-extern"))) void w(void) {}
// expected-warning@+1 {{'function_return' attribute argument not supported: invalid}}
__attribute__((function_return("invalid"))) void v(void) {}

// expected-error@+1 {{'function_return' attribute requires a string}}
// expected-error@+1 {{expected string literal as argument of 'function_return' attribute}}
__attribute__((function_return(5))) void a(void) {}

// expected-error@+1 {{'function_return' attribute takes one argument}}
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Sema/callingconv-iamcu.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ int __attribute__((pcs("aapcs", "aapcs"))) pcs1(void); // expected-error {{'pcs'
int __attribute__((pcs())) pcs2(void); // expected-error {{'pcs' attribute takes one argument}}
int __attribute__((pcs(pcs1))) pcs3(void); // expected-error {{'pcs' attribute requires a string}} \
// expected-error {{invalid PCS type}}
int __attribute__((pcs(0))) pcs4(void); // expected-error {{'pcs' attribute requires a string}}
int __attribute__((pcs(0))) pcs4(void); // expected-error {{expected string literal as argument of 'pcs' attribute}}
/* These are ignored because the target is i386 and not ARM */
int __attribute__((pcs("aapcs"))) pcs5(void); // expected-warning {{'pcs' calling convention is not supported for this target}}
int __attribute__((pcs("aapcs-vfp"))) pcs6(void); // expected-warning {{'pcs' calling convention is not supported for this target}}
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Sema/callingconv.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ int __attribute__((pcs("aapcs", "aapcs"))) pcs1(void); // expected-error {{'pcs'
int __attribute__((pcs())) pcs2(void); // expected-error {{'pcs' attribute takes one argument}}
int __attribute__((pcs(pcs1))) pcs3(void); // expected-error {{'pcs' attribute requires a string}} \
// expected-error {{invalid PCS type}}
int __attribute__((pcs(0))) pcs4(void); // expected-error {{'pcs' attribute requires a string}}
int __attribute__((pcs(0))) pcs4(void); // expected-error {{expected string literal as argument of 'pcs' attribute}}
/* These are ignored because the target is i386 and not ARM */
int __attribute__((pcs("aapcs"))) pcs5(void); // expected-warning {{'pcs' calling convention is not supported for this target}}
int __attribute__((pcs("aapcs-vfp"))) pcs6(void); // expected-warning {{'pcs' calling convention is not supported for this target}}
Expand Down
Loading