[clang] [llvm] [RISCV] Add riscv_atomics.h and Zawrs/Zalrsc builtins (PR #94578)
https://github.com/wangpc-pp updated https://github.com/llvm/llvm-project/pull/94578 >From 57c914eaefa7e59aa51a2b1e730fe1b7d6d10e57 Mon Sep 17 00:00:00 2001 From: Wang Pengcheng Date: Thu, 6 Jun 2024 13:48:34 +0800 Subject: [PATCH 1/3] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20in?= =?UTF-8?q?itial=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.6-beta.1 --- clang/include/clang/Basic/BuiltinsRISCV.td| 18 ++ clang/lib/CodeGen/CGBuiltin.cpp | 22 ++ clang/lib/Headers/CMakeLists.txt | 1 + clang/lib/Headers/riscv_atomics.h | 36 +++ clang/lib/Sema/SemaRISCV.cpp | 10 +- .../RISCV/atomics-intrinsics/zalrsc-error.c | 13 + .../CodeGen/RISCV/atomics-intrinsics/zalrsc.c | 222 ++ .../CodeGen/RISCV/atomics-intrinsics/zawrs.c | 42 llvm/include/llvm/IR/IntrinsicsRISCV.td | 32 +++ llvm/lib/Target/RISCV/RISCVInstrInfoA.td | 25 ++ llvm/lib/Target/RISCV/RISCVInstrInfoZa.td | 5 +- llvm/test/CodeGen/RISCV/zalrsc-rv32.ll| 74 ++ llvm/test/CodeGen/RISCV/zalrsc-rv64.ll| 74 ++ llvm/test/CodeGen/RISCV/zawrs.ll | 33 +++ 14 files changed, 605 insertions(+), 2 deletions(-) create mode 100644 clang/lib/Headers/riscv_atomics.h create mode 100644 clang/test/CodeGen/RISCV/atomics-intrinsics/zalrsc-error.c create mode 100644 clang/test/CodeGen/RISCV/atomics-intrinsics/zalrsc.c create mode 100644 clang/test/CodeGen/RISCV/atomics-intrinsics/zawrs.c create mode 100644 llvm/test/CodeGen/RISCV/zalrsc-rv32.ll create mode 100644 llvm/test/CodeGen/RISCV/zalrsc-rv64.ll create mode 100644 llvm/test/CodeGen/RISCV/zawrs.ll diff --git a/clang/include/clang/Basic/BuiltinsRISCV.td b/clang/include/clang/Basic/BuiltinsRISCV.td index 4cc89a8a9d8af..458c755179417 100644 --- a/clang/include/clang/Basic/BuiltinsRISCV.td +++ b/clang/include/clang/Basic/BuiltinsRISCV.td @@ -146,3 +146,21 @@ let Features = "zihintntl", Attributes = [CustomTypeChecking] in { def ntl_load : RISCVBuiltin<"void(...)">; def ntl_store : RISCVBuiltin<"void(...)">; } // Features = "zihintntl", Attributes = [CustomTypeChecking] + +//===--===// +// Zawrs extension. +//===--===// +let Features = "zawrs" in { +def wrs_nto : RISCVBuiltin<"void()">; +def wrs_sto : RISCVBuiltin<"void()">; +} // Features = "zawrs" + +//===--===// +// Zalrsc extension. +//===--===// +let Features = "zalrsc" in { +def lr_w : RISCVBuiltin<"int(int *, _Constant unsigned int)">; +def lr_d : RISCVBuiltin<"int64_t(int64_t *, _Constant unsigned int)">; +def sc_w : RISCVBuiltin<"int(int, int *, _Constant unsigned int)">; +def sc_d : RISCVBuiltin<"int64_t(int64_t, int64_t *, _Constant unsigned int)">; +} // Features = "zalrsc" diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 37d0c478e0330..db48c69e10c86 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -21769,6 +21769,28 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID, ID = Intrinsic::riscv_sm3p1; break; + // Zawrs + case RISCV::BI__builtin_riscv_wrs_nto: +ID = Intrinsic::riscv_wrs_nto; +break; + case RISCV::BI__builtin_riscv_wrs_sto: +ID = Intrinsic::riscv_wrs_sto; +break; + + // Zalrsc + case RISCV::BI__builtin_riscv_lr_w: +ID = Intrinsic::riscv_lr_w; +break; + case RISCV::BI__builtin_riscv_lr_d: +ID = Intrinsic::riscv_lr_d; +break; + case RISCV::BI__builtin_riscv_sc_w: +ID = Intrinsic::riscv_sc_w; +break; + case RISCV::BI__builtin_riscv_sc_d: +ID = Intrinsic::riscv_sc_d; +break; + // Zihintntl case RISCV::BI__builtin_riscv_ntl_load: { llvm::Type *ResTy = ConvertType(E->getType()); diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt index d3090e488306f..cf2fbf1893772 100644 --- a/clang/lib/Headers/CMakeLists.txt +++ b/clang/lib/Headers/CMakeLists.txt @@ -118,6 +118,7 @@ set(ppc_htm_files ) set(riscv_files + riscv_atomics.h riscv_bitmanip.h riscv_crypto.h riscv_ntlh.h diff --git a/clang/lib/Headers/riscv_atomics.h b/clang/lib/Headers/riscv_atomics.h new file mode 100644 index 0..35db57fe36131 --- /dev/null +++ b/clang/lib/Headers/riscv_atomics.h @@ -0,0 +1,36 @@ +/*=== riscv_atomics.h - RISC-V atomics intrinsics --=== + * + * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + * See https://llvm.org/LICENSE.txt for license information. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + * + *===--
[clang] [llvm] [clang] Reland Add tanf16 builtin and support for tan constrained intrinsic (PR #94559)
https://github.com/farzonl edited https://github.com/llvm/llvm-project/pull/94559 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] NFCI: Make ASTContext optional in the AST text dumper again (PR #94522)
https://github.com/tbaederr approved this pull request. Can't say much about this functionally, but it fixes my problems, so LGTM from that side. https://github.com/llvm/llvm-project/pull/94522 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] CWG2749: relational operators involving pointers to void (PR #93046)
https://github.com/tbaederr approved this pull request. LGTM. I guess we should close https://github.com/llvm/llvm-project/pull/89449 after merging this. https://github.com/llvm/llvm-project/pull/93046 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] fb0c705 - [clang] NFCI: Make ASTContext optional in the AST text dumper again (#94522)
Author: Matheus Izvekov Date: 2024-06-06T04:14:10-03:00 New Revision: fb0c705dbf27e3ab84d726ad30e172806a530c21 URL: https://github.com/llvm/llvm-project/commit/fb0c705dbf27e3ab84d726ad30e172806a530c21 DIFF: https://github.com/llvm/llvm-project/commit/fb0c705dbf27e3ab84d726ad30e172806a530c21.diff LOG: [clang] NFCI: Make ASTContext optional in the AST text dumper again (#94522) Added: Modified: clang/lib/AST/TextNodeDumper.cpp clang/lib/AST/Type.cpp Removed: diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index 8bacceea0f22b..1076dcd40a694 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -958,6 +958,9 @@ void TextNodeDumper::dumpTemplateArgument(const TemplateArgument &TA) { } OS << " '" << Str << "'"; + if (!Context) +return; + if (TemplateArgument CanonTA = Context->getCanonicalTemplateArgument(TA); !CanonTA.structurallyEquals(TA)) { llvm::SmallString<128> CanonStr; @@ -1139,15 +1142,17 @@ void TextNodeDumper::dumpTemplateName(TemplateName TN, StringRef Label) { } OS << " '" << Str << "'"; - if (TemplateName CanonTN = Context->getCanonicalTemplateName(TN); - CanonTN != TN) { -llvm::SmallString<128> CanonStr; -{ - llvm::raw_svector_ostream SS(CanonStr); - CanonTN.print(SS, PrintPolicy); + if (Context) { +if (TemplateName CanonTN = Context->getCanonicalTemplateName(TN); +CanonTN != TN) { + llvm::SmallString<128> CanonStr; + { +llvm::raw_svector_ostream SS(CanonStr); +CanonTN.print(SS, PrintPolicy); + } + if (CanonStr != Str) +OS << ":'" << CanonStr << "'"; } -if (CanonStr != Str) - OS << ":'" << CanonStr << "'"; } } dumpBareTemplateName(TN); diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 3f88c3441eaf6..33acae2cbafac 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -4481,7 +4481,6 @@ static CachedProperties computeCachedProperties(const Type *T) { #define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class,Base) case Type::Class: #include "clang/AST/TypeNodes.inc" // Treat instantiation-dependent types as external. -if (!T->isInstantiationDependentType()) T->dump(); assert(T->isInstantiationDependentType()); return CachedProperties(Linkage::External, false); ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] NFCI: Make ASTContext optional in the AST text dumper again (PR #94522)
https://github.com/mizvekov closed https://github.com/llvm/llvm-project/pull/94522 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [PowerPC] Support -mno-red-zone option (PR #94581)
https://github.com/chenzheng1030 commented: Are there backend cases that shows with -disable-red-zone, the final assembly is still correct? https://github.com/llvm/llvm-project/pull/94581 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [PowerPC] Support -mno-red-zone option (PR #94581)
https://github.com/chenzheng1030 edited https://github.com/llvm/llvm-project/pull/94581 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [AArch64] Decouple feature dependency expansion. (PR #94279)
labrinea wrote: > Not supporting "neon" as a name would seem like a mistake if it was removed, > but I don't believe this patch does that. It does https://github.com/llvm/llvm-project/pull/94279 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Refine invalidation caused by `fread` (PR #93408)
@@ -907,6 +945,73 @@ void StreamChecker::preWrite(const FnDescription *Desc, const CallEvent &Call, C.addTransition(State); } +static std::optional getPointeeType(const MemRegion *R) { + if (!R) +return std::nullopt; + if (const auto *ER = dyn_cast(R)) +return ER->getElementType(); + if (const auto *TR = dyn_cast(R)) +return TR->getValueType(); + if (const auto *SR = dyn_cast(R)) +return SR->getPointeeStaticType(); + return std::nullopt; +} + +static std::optional getStartIndex(SValBuilder &SVB, + const MemRegion *R) { + if (!R) +return std::nullopt; + + auto Zero = [&SVB] { +BasicValueFactory &BVF = SVB.getBasicValueFactory(); +return nonloc::ConcreteInt(BVF.getIntValue(0, /*isUnsigned=*/false)); + }; steakhal wrote: This way it's lazily evaluated. https://github.com/llvm/llvm-project/pull/93408 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Refine invalidation caused by `fread` (PR #93408)
@@ -0,0 +1,412 @@ +// RUN: %clang_analyze_cc1 -verify %s \ +// RUN: -triple x86_64-linux-gnu \ +// RUN: -analyzer-checker=core,unix.Stream,alpha.security.taint \ +// RUN: -analyzer-checker=debug.ExprInspection + +#include "Inputs/system-header-simulator-for-simple-stream.h" + +#define EOF (-1) + +void clang_analyzer_dump(int); +void clang_analyzer_isTainted(int); +void clang_analyzer_warnIfReached(void); + +// A stream is only tracked by StreamChecker if it results from a call to "fopen". +// Otherwise, there is no specific modelling of "fread". +void untracked_stream(FILE *fp) { + char c; + if (1 == fread(&c, 1, 1, fp)) { +char p = c; // Unknown value but not garbage and not modeled by checker. + } else { +char p = c; // Possibly indeterminate value but not modeled by checker. + } +} + +void fgetc_props_taint(void) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +int c = fgetc(fp); // c is tainted. +if (c != EOF) { + clang_analyzer_isTainted(c); // expected-warning{{YES}} +} +fclose(fp); + } +} + +void fread_props_taint(void) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +char buffer[10]; +int c = fread(buffer, 1, 10, fp); // c is tainted. +if (c != 10) { + // If the read failed, then the number of bytes successfully read should be tainted. + clang_analyzer_isTainted(c); // expected-warning{{YES}} +} +fclose(fp); + } +} + +void read_one_byte1(void) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +char c; +if (1 == fread(&c, 1, 1, fp)) { + char p = c; // Unknown value but not garbage. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} else { + char p = c; // Possibly indeterminate value but not modeled by checker. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} +fclose(fp); + } +} + +void read_one_byte2(char *buffer) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +if (1 == fread(buffer, 1, 1, fp)) { + char p = buffer[0]; // Unknown value but not garbage. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} else { + char p = buffer[0]; // Possibly indeterminate value but not modeled by checker. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} +fclose(fp); + } +} + +void read_one_byte3(char *buffer) { + buffer[1] = 10; + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +// buffer[1] is not mutated by fread and remains not tainted. +fread(buffer, 1, 1, fp); +char p = buffer[1]; +clang_analyzer_isTainted(p); // expected-warning{{NO}} +clang_analyzer_dump(buffer[1]); // expected-warning{{10 S32b}} +fclose(fp); + } +} + +void read_many_bytes(char *buffer) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +if (42 == fread(buffer, 1, 42, fp)) { + char p = buffer[0]; // Unknown value but not garbage. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} else { + char p = buffer[0]; // Possibly indeterminate value but not modeled. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} +fclose(fp); + } +} + +void random_access_write1(int index) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +long c[4]; +int success = 2 == fread(c + 1, sizeof(long), 2, fp); + +switch (index) { +case 0: + // c[0] is not mutated by fread. + if (success) { +char p = c[0]; // expected-warning {{Assigned value is garbage or undefined}} We kept the first byte intact. + } else { +char p = c[0]; // expected-warning {{Assigned value is garbage or undefined}} We kept the first byte intact. + } + break; + +case 1: + if (success) { +// Unknown value but not garbage. +clang_analyzer_isTainted(c[1]); // expected-warning {{YES}} +clang_analyzer_dump(c[1]); // expected-warning {{conj_}} + } else { +// Possibly indeterminate value but not modeled. +clang_analyzer_isTainted(c[1]); // expected-warning {{YES}} +clang_analyzer_dump(c[1]); // expected-warning {{conj_}} + } + break; + +case 2: + if (success) { +long p = c[2]; // Unknown value but not garbage. +// FIXME: Taint analysis only marks the first byte of a memory region. See getPointeeOf in GenericTaintChecker.cpp. +clang_analyzer_isTainted(c[2]); // expected-warning {{NO}} +clang_analyzer_dump(c[2]); // expected-warning {{conj_}} + } else { +// Possibly indeterminate value but not modeled. +clang_analyzer_isTainted(c[2]); // expected-warning {{NO}} // FIXME: See above. +clang_analyzer_dump(c[2]); // expected-warning {{conj_}} + } + break; + +case 3: + // c[3] is not mutated by fread. + if (success) { +long p = c[3]; // expected-warning {{Assigned value is garbage or undefined}} + } else { +long p = c[3]; // ex
[clang] [PowerPC] Support -mno-red-zone option (PR #94581)
ecnelises wrote: No. `-disable-red-zone` does nothing but add `noredzone` IR attribute to functions. We need to add cases to test for `noredzone` behavior on PPC (arm and x86 have). https://github.com/llvm/llvm-project/pull/94581 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Refine invalidation caused by `fread` (PR #93408)
https://github.com/steakhal edited https://github.com/llvm/llvm-project/pull/93408 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Support [[guarded_by(mutex)]] attribute inside C struct (PR #94216)
pdherbemont wrote: > LGTM assuming you will be fixing the buildkite failures. > > You may still need to wait on @AaronBallman's approval. Fixed the buildkite issue – they were regression from the latest changes about acquired_{before,after} handling. Also pinged @AaronBallman. Thank you all for the feedback! https://github.com/llvm/llvm-project/pull/94216 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] add an option to insert a space only for non-code block empty braces, not for empty parentheses (PR #93634)
https://github.com/khei4 updated https://github.com/llvm/llvm-project/pull/93634 >From 4cdd7bd2a916740f886939d1ec0395b5915eb3c2 Mon Sep 17 00:00:00 2001 From: Kohei Asano Date: Mon, 3 Jun 2024 09:15:44 +0900 Subject: [PATCH 1/2] [clang-format] add an option to insert a space only for empty braces --- clang/docs/ClangFormatStyleOptions.rst | 97 - clang/include/clang/Format/Format.h | 112 ++-- clang/lib/Format/Format.cpp | 40 ++- clang/lib/Format/TokenAnnotator.cpp | 18 +++- clang/lib/Format/UnwrappedLineFormatter.cpp | 13 ++- clang/unittests/Format/ConfigParseTest.cpp | 9 +- clang/unittests/Format/FormatTest.cpp | 99 - 7 files changed, 368 insertions(+), 20 deletions(-) diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index bb00c20922d36..9879d122f8d57 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -6036,12 +6036,103 @@ the configuration (without a prefix: ``Auto``). **SpaceInEmptyBlock** (``Boolean``) :versionbadge:`clang-format 10` :ref:`¶ ` If ``true``, spaces will be inserted into ``{}``. + This option is **deprecated**. The previous behavior is preserved by using + ``SpaceInEmptyBraces`` with ``Custom`` and by setting ``Block`` in + ``SpaceInEmptyBracesOptions`` to ``true``. + +.. _SpaceInEmptyBraces: + +**SpaceInEmptyBraces** (``SpaceInEmptyBracesStyle``) :versionbadge:`clang-format 19` :ref:`¶ ` + Defines in which cases spaces will be inserted in empty braces. + + Possible values: + + * ``SIEBO_Never`` (in configuration: ``Never``) +Never put a space in empty braces. + +.. code-block:: c++ + + void f() {} + T x{}; + while (true) {} + struct U1 {}; + union U2 {}; + class U3 {}; + enum U4 {}; + + * ``SIEBO_Custom`` (in configuration: ``Custom``) +Configure each individual space in empty braces in +`SpacesInEmptyBracesOptions`. + + + +.. _SpaceInEmptyBracesOptions: + +**SpaceInEmptyBracesOptions** (``SpaceInEmptyBracesCustom``) :versionbadge:`clang-format 19` :ref:`¶ ` + Control of individual spaces in empty braces. + + If ``SpaceInEmptyBraces`` is set to ``Custom``, use this to specify + how each individual space in empty braces case should be handled. + Otherwise, this is ignored. + + .. code-block:: yaml + +# Example of usage: +SpaceInEmptyBraces: Custom +SpaceInEmptyBracesOptions: + Function: true + Record: false + InitList: true + Block: false + + Nested configuration flags: + + Precise control over the spacing in empty braces. .. code-block:: c++ - true:false: - void f() { } vs. void f() {} - while (true) { } while (true) {} +# Should be declared this way: +SpaceInEmptyBraces: Custom +SpaceInEmptyBracesOptions: + Function: true + Record: false + InitList: true + Block: false + + * ``bool Function`` Put a space in empty braces of function definition. + +.. code-block:: c++ + + true: false: + void f() { } vs. void f() {} + + * ``bool Record`` Put a space in empty braces of record/struct definition. + +.. code-block:: c++ + + true: false: + struct U1 { }; vs. struct U1 {}; + union U2 { }; union U2 {}; + class U3 { }; class U3 {}; + enum U4 { }; enum U4 {}; + + * ``bool InitList`` Put a space in empty braces of initializer list. + +.. code-block:: c++ + + true: false: + T x{ };vs. T x{}; + + * ``bool Block`` Put a space in empty braces of other blocks, including functions and +record, compatible with ``SpaceInEmptyBlock``. + +.. code-block:: c++ + + true: false: + void f() { } vs. void f() {} + enum Unit { }; enum Unit {}; + while (true) { } while (true) {} + .. _SpaceInEmptyParentheses: diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 4fd6e013df25b..a6d8700ad9aa3 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -4493,13 +4493,11 @@ struct FormatStyle { bool SpaceBeforeRangeBasedForLoopColon; /// If ``true``, spaces will be inserted into ``{}``. - /// \code - ///true:false: - ///void f() { } vs. void f() {} - ///while (true) { } while (true) {} - /// \endcode + /// This option is **deprecated**. The previous behavior is preserved
[clang] [analyzer] Refine invalidation caused by `fread` (PR #93408)
@@ -0,0 +1,412 @@ +// RUN: %clang_analyze_cc1 -verify %s \ +// RUN: -triple x86_64-linux-gnu \ +// RUN: -analyzer-checker=core,unix.Stream,alpha.security.taint \ +// RUN: -analyzer-checker=debug.ExprInspection + +#include "Inputs/system-header-simulator-for-simple-stream.h" + +#define EOF (-1) + +void clang_analyzer_dump(int); +void clang_analyzer_isTainted(int); +void clang_analyzer_warnIfReached(void); + +// A stream is only tracked by StreamChecker if it results from a call to "fopen". +// Otherwise, there is no specific modelling of "fread". +void untracked_stream(FILE *fp) { + char c; + if (1 == fread(&c, 1, 1, fp)) { +char p = c; // Unknown value but not garbage and not modeled by checker. + } else { +char p = c; // Possibly indeterminate value but not modeled by checker. + } +} + +void fgetc_props_taint(void) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +int c = fgetc(fp); // c is tainted. +if (c != EOF) { + clang_analyzer_isTainted(c); // expected-warning{{YES}} +} +fclose(fp); + } +} + +void fread_props_taint(void) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +char buffer[10]; +int c = fread(buffer, 1, 10, fp); // c is tainted. +if (c != 10) { + // If the read failed, then the number of bytes successfully read should be tainted. + clang_analyzer_isTainted(c); // expected-warning{{YES}} +} +fclose(fp); + } +} + +void read_one_byte1(void) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +char c; +if (1 == fread(&c, 1, 1, fp)) { + char p = c; // Unknown value but not garbage. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} else { + char p = c; // Possibly indeterminate value but not modeled by checker. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} +fclose(fp); + } +} + +void read_one_byte2(char *buffer) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +if (1 == fread(buffer, 1, 1, fp)) { + char p = buffer[0]; // Unknown value but not garbage. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} else { + char p = buffer[0]; // Possibly indeterminate value but not modeled by checker. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} +fclose(fp); + } +} + +void read_one_byte3(char *buffer) { + buffer[1] = 10; + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +// buffer[1] is not mutated by fread and remains not tainted. +fread(buffer, 1, 1, fp); +char p = buffer[1]; +clang_analyzer_isTainted(p); // expected-warning{{NO}} +clang_analyzer_dump(buffer[1]); // expected-warning{{10 S32b}} +fclose(fp); + } +} + +void read_many_bytes(char *buffer) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +if (42 == fread(buffer, 1, 42, fp)) { + char p = buffer[0]; // Unknown value but not garbage. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} else { + char p = buffer[0]; // Possibly indeterminate value but not modeled. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} +fclose(fp); + } +} + +void random_access_write1(int index) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +long c[4]; +int success = 2 == fread(c + 1, sizeof(long), 2, fp); + +switch (index) { +case 0: + // c[0] is not mutated by fread. + if (success) { +char p = c[0]; // expected-warning {{Assigned value is garbage or undefined}} We kept the first byte intact. + } else { +char p = c[0]; // expected-warning {{Assigned value is garbage or undefined}} We kept the first byte intact. + } + break; + +case 1: + if (success) { +// Unknown value but not garbage. +clang_analyzer_isTainted(c[1]); // expected-warning {{YES}} +clang_analyzer_dump(c[1]); // expected-warning {{conj_}} + } else { +// Possibly indeterminate value but not modeled. +clang_analyzer_isTainted(c[1]); // expected-warning {{YES}} +clang_analyzer_dump(c[1]); // expected-warning {{conj_}} + } + break; + +case 2: + if (success) { +long p = c[2]; // Unknown value but not garbage. +// FIXME: Taint analysis only marks the first byte of a memory region. See getPointeeOf in GenericTaintChecker.cpp. +clang_analyzer_isTainted(c[2]); // expected-warning {{NO}} +clang_analyzer_dump(c[2]); // expected-warning {{conj_}} + } else { +// Possibly indeterminate value but not modeled. +clang_analyzer_isTainted(c[2]); // expected-warning {{NO}} // FIXME: See above. +clang_analyzer_dump(c[2]); // expected-warning {{conj_}} + } + break; + +case 3: + // c[3] is not mutated by fread. + if (success) { +long p = c[3]; // expected-warning {{Assigned value is garbage or undefined}} + } else { +long p = c[3]; // ex
[clang] [analyzer] Factor out NoOwnershipChangeVisitor (PR #94357)
Szelethus wrote: Yes, it is, sorry about that :) https://github.com/llvm/llvm-project/pull/94357 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer][NFC] Factor out NoOwnershipChangeVisitor (PR #94357)
https://github.com/Szelethus edited https://github.com/llvm/llvm-project/pull/94357 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Refine invalidation caused by `fread` (PR #93408)
@@ -0,0 +1,412 @@ +// RUN: %clang_analyze_cc1 -verify %s \ +// RUN: -triple x86_64-linux-gnu \ +// RUN: -analyzer-checker=core,unix.Stream,alpha.security.taint \ +// RUN: -analyzer-checker=debug.ExprInspection + +#include "Inputs/system-header-simulator-for-simple-stream.h" + +#define EOF (-1) + +void clang_analyzer_dump(int); +void clang_analyzer_isTainted(int); +void clang_analyzer_warnIfReached(void); + +// A stream is only tracked by StreamChecker if it results from a call to "fopen". +// Otherwise, there is no specific modelling of "fread". +void untracked_stream(FILE *fp) { + char c; + if (1 == fread(&c, 1, 1, fp)) { +char p = c; // Unknown value but not garbage and not modeled by checker. + } else { +char p = c; // Possibly indeterminate value but not modeled by checker. + } +} + +void fgetc_props_taint(void) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +int c = fgetc(fp); // c is tainted. +if (c != EOF) { + clang_analyzer_isTainted(c); // expected-warning{{YES}} +} +fclose(fp); + } +} + +void fread_props_taint(void) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +char buffer[10]; +int c = fread(buffer, 1, 10, fp); // c is tainted. +if (c != 10) { + // If the read failed, then the number of bytes successfully read should be tainted. + clang_analyzer_isTainted(c); // expected-warning{{YES}} +} +fclose(fp); + } +} + +void read_one_byte1(void) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +char c; +if (1 == fread(&c, 1, 1, fp)) { + char p = c; // Unknown value but not garbage. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} else { + char p = c; // Possibly indeterminate value but not modeled by checker. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} +fclose(fp); + } +} + +void read_one_byte2(char *buffer) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +if (1 == fread(buffer, 1, 1, fp)) { + char p = buffer[0]; // Unknown value but not garbage. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} else { + char p = buffer[0]; // Possibly indeterminate value but not modeled by checker. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} +fclose(fp); + } +} + +void read_one_byte3(char *buffer) { + buffer[1] = 10; + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +// buffer[1] is not mutated by fread and remains not tainted. +fread(buffer, 1, 1, fp); +char p = buffer[1]; +clang_analyzer_isTainted(p); // expected-warning{{NO}} +clang_analyzer_dump(buffer[1]); // expected-warning{{10 S32b}} +fclose(fp); + } +} + +void read_many_bytes(char *buffer) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +if (42 == fread(buffer, 1, 42, fp)) { + char p = buffer[0]; // Unknown value but not garbage. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} else { + char p = buffer[0]; // Possibly indeterminate value but not modeled. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} +fclose(fp); + } +} + +void random_access_write1(int index) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +long c[4]; +int success = 2 == fread(c + 1, sizeof(long), 2, fp); + +switch (index) { +case 0: + // c[0] is not mutated by fread. + if (success) { +char p = c[0]; // expected-warning {{Assigned value is garbage or undefined}} We kept the first byte intact. + } else { +char p = c[0]; // expected-warning {{Assigned value is garbage or undefined}} We kept the first byte intact. + } + break; + +case 1: + if (success) { +// Unknown value but not garbage. +clang_analyzer_isTainted(c[1]); // expected-warning {{YES}} +clang_analyzer_dump(c[1]); // expected-warning {{conj_}} + } else { +// Possibly indeterminate value but not modeled. +clang_analyzer_isTainted(c[1]); // expected-warning {{YES}} +clang_analyzer_dump(c[1]); // expected-warning {{conj_}} + } + break; + +case 2: + if (success) { +long p = c[2]; // Unknown value but not garbage. +// FIXME: Taint analysis only marks the first byte of a memory region. See getPointeeOf in GenericTaintChecker.cpp. +clang_analyzer_isTainted(c[2]); // expected-warning {{NO}} +clang_analyzer_dump(c[2]); // expected-warning {{conj_}} + } else { +// Possibly indeterminate value but not modeled. +clang_analyzer_isTainted(c[2]); // expected-warning {{NO}} // FIXME: See above. +clang_analyzer_dump(c[2]); // expected-warning {{conj_}} + } + break; + +case 3: + // c[3] is not mutated by fread. + if (success) { +long p = c[3]; // expected-warning {{Assigned value is garbage or undefined}} + } else { +long p = c[3]; // ex
[clang] [llvm] [clang][SPIR-V] Add support for AMDGCN flavoured SPIRV (PR #89796)
@@ -114,15 +118,17 @@ Example: ``-target spirv64v1.0`` can be used to compile for SPIR-V version 1.0 with 64-bit pointer width. +``-target spirv64-amd-amdhsa`` can be used to compile for AMDGCN flavoured SPIR-V version 1.6 with 64-bit pointer width VyacheslavLevytskyy wrote: I'm not sure how the number of the version 1.6 will be deducted from just `spirv64-amd-amdhsa`. https://github.com/llvm/llvm-project/pull/89796 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] `doesNotMutateObject`: Handle calls to member functions … (PR #94362)
@@ -36,6 +36,111 @@ void extractNodesByIdTo(ArrayRef Matches, StringRef ID, Nodes.insert(Match.getNodeAs(ID)); } +// If `D` has a const-qualified overload with otherwise identical +// ref-qualifiers, returns that overload. +const CXXMethodDecl *findConstOverload(const CXXMethodDecl &D) { + assert(!D.isConst()); + + DeclContext::lookup_result lookup_result = + D.getParent()->lookup(D.getNameInfo().getName()); + if (lookup_result.isSingleResult()) { +// No overload. +return nullptr; + } + for (const Decl *overload : lookup_result) { +const CXXMethodDecl *candidate = dyn_cast(overload); +if (candidate && !candidate->isDeleted() && candidate->isConst() && +candidate->getRefQualifier() == D.getRefQualifier()) { + return candidate; +} + } + return nullptr; +} + +// Returns true if both types refer to the same to the same type, +// ignoring the const-qualifier. +bool isSameTypeIgnoringConst(QualType A, QualType B) { + A = A.getCanonicalType(); + B = B.getCanonicalType(); + A.addConst(); + B.addConst(); + return A == B; +} + +// Returns true if both types are pointers or reference to the same type, +// ignoring the const-qualifier. +bool pointsToSameTypeIgnoringConst(QualType A, QualType B) { + assert(A->isPointerType() || A->isReferenceType()); + assert(B->isPointerType() || B->isReferenceType()); + return isSameTypeIgnoringConst(A->getPointeeType(), B->getPointeeType()); +} + +// Return true if non-const member function `M` likely does not mutate `*this`. +// +// Note that if the member call selects a method/operator `f` that +// is not const-qualified, then we also consider that the object is +// not mutated if: +// - (A) there is a const-qualified overload `cf` of `f` that has +// the +//same ref-qualifiers; +// - (B) * `f` returns a value, or +//* if `f` returns a `T&`, `cf` returns a `const T&` (up to +// possible aliases such as `reference` and +// `const_reference`), or +//* if `f` returns a `T*`, `cf` returns a `const T*` (up to +// possible aliases). +// - (C) the result of the call is not mutated. +// +// The assumption that `cf` has the same semantics as `f`. +// For example: +// - In `std::vector v; const T t = v[...];`, we consider that +// expression `v[...]` does not mutate `v` as +//`T& std::vector::operator[]` has a const overload +// `const T& std::vector::operator[] const`, and the +// result expression of type `T&` is only used as a `const T&`; +// - In `std::map m; V v = m.at(...);`, we consider +// `m.at(...)` to be an immutable access for the same reason. +// However: +// - In `std::map m; const V v = m[...];`, We consider that +// `m[...]` mutates `m` as `V& std::map::operator[]` does +// not have a const overload. +// - In `std::vector v; T& t = v[...];`, we consider that +// expression `v[...]` mutates `v` as the result is kept as a +// mutable reference. +// +// This function checks (A) ad (B), but the caller should make sure that the +// object is not mutated through the return value. +bool isLikelyShallowConst(const CXXMethodDecl &M) { + assert(!M.isConst()); + // The method can mutate our variable. + + // (A) + const CXXMethodDecl *ConstOverload = findConstOverload(M); + if (ConstOverload == nullptr) { +return false; + } + + // (B) + const QualType CallTy = M.getReturnType().getCanonicalType(); + const QualType OverloadTy = ConstOverload->getReturnType().getCanonicalType(); + if (CallTy->isReferenceType()) { +if (!(OverloadTy->isReferenceType() && + pointsToSameTypeIgnoringConst(CallTy, OverloadTy))) { + return false; +} legrosbuffle wrote: Much clearer, thanks. https://github.com/llvm/llvm-project/pull/94362 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][SPIR-V] Add support for AMDGCN flavoured SPIRV (PR #89796)
@@ -0,0 +1,35 @@ +; RUN: llc -O0 -mtriple=spirv64-amd-amdhsa --spirv-ext=+SPV_INTEL_function_pointers %s -o - | FileCheck %s +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-amd-amdhsa %s -o - -filetype=obj | spirv-val %} + +; CHECK-DAG: OpCapability Int8 +; CHECK-DAG: OpCapability GenericPointer +; CHECK-DAG: OpCapability FunctionPointersINTEL +; CHECK-DAG: OpCapability Int64 +; CHECK: OpExtension "SPV_INTEL_function_pointers" +; CHECK-DAG: %[[TyInt8:.*]] = OpTypeInt 8 0 +; CHECK-DAG: %[[TyVoid:.*]] = OpTypeVoid +; CHECK-DAG: %[[TyInt64:.*]] = OpTypeInt 64 0 +; CHECK-DAG: %[[TyFunFp:.*]] = OpTypeFunction %[[TyVoid]] %[[TyInt64]] +; CHECK-DAG: %[[ConstInt64:.*]] = OpConstant %[[TyInt64]] 42 +; CHECK-DAG: %[[TyPtrFunFp:.*]] = OpTypePointer Generic %[[TyFunFp]] +; CHECK-DAG: %[[ConstFunFp:.*]] = OpConstantFunctionPointerINTEL %[[TyPtrFunFp]] %[[DefFunFp:.*]] +; CHECK: %[[FunPtr1:.*]] = OpBitcast %[[#]] %[[ConstFunFp]] +; CHECK: %[[FunPtr2:.*]] = OpLoad %[[#]] %[[FunPtr1]] +; CHECK: OpFunctionPointerCallINTEL %[[TyInt64]] %[[FunPtr2]] %[[ConstInt64]] +; CHECK: OpReturn +; CHECK: OpFunctionEnd +; CHECK: %[[DefFunFp]] = OpFunction %[[TyVoid]] None %[[TyFunFp]] + +target triple = "spir64-unknown-unknown" VyacheslavLevytskyy wrote: Probably this line is not needed here? https://github.com/llvm/llvm-project/pull/89796 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [clang][SPIR-V] Add support for AMDGCN flavoured SPIRV (PR #89796)
@@ -0,0 +1,35 @@ +; RUN: llc -O0 -mtriple=spirv64-amd-amdhsa --spirv-ext=+SPV_INTEL_function_pointers %s -o - | FileCheck %s +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-amd-amdhsa %s -o - -filetype=obj | spirv-val %} + +; CHECK-DAG: OpCapability Int8 +; CHECK-DAG: OpCapability GenericPointer +; CHECK-DAG: OpCapability FunctionPointersINTEL +; CHECK-DAG: OpCapability Int64 +; CHECK: OpExtension "SPV_INTEL_function_pointers" +; CHECK-DAG: %[[TyInt8:.*]] = OpTypeInt 8 0 +; CHECK-DAG: %[[TyVoid:.*]] = OpTypeVoid +; CHECK-DAG: %[[TyFloat32:.*]] = OpTypeFloat 32 +; CHECK-DAG: %[[TyInt64:.*]] = OpTypeInt 64 0 +; CHECK-DAG: %[[TyPtrInt8:.*]] = OpTypePointer Generic %[[TyInt8]] +; CHECK-DAG: %[[TyFunFp:.*]] = OpTypeFunction %[[TyFloat32]] %[[TyPtrInt8]] +; CHECK-DAG: %[[TyFunBar:.*]] = OpTypeFunction %[[TyInt64]] %[[TyPtrInt8]] %[[TyPtrInt8]] +; CHECK-DAG: %[[TyPtrFunFp:.*]] = OpTypePointer Function %[[TyFunFp]] +; CHECK-DAG: %[[TyPtrFunBar:.*]] = OpTypePointer Function %[[TyFunBar]] +; CHECK-DAG: %[[TyFunTest:.*]] = OpTypeFunction %[[TyVoid]] %[[TyPtrInt8]] %[[TyPtrInt8]] %[[TyPtrInt8]] +; CHECK: %[[FunTest:.*]] = OpFunction %[[TyVoid]] None %[[TyFunTest]] +; CHECK: %[[ArgFp:.*]] = OpFunctionParameter %[[TyPtrInt8]] +; CHECK: %[[ArgData:.*]] = OpFunctionParameter %[[TyPtrInt8]] +; CHECK: %[[ArgBar:.*]] = OpFunctionParameter %[[TyPtrInt8]] +; CHECK: OpFunctionPointerCallINTEL %[[TyFloat32]] %[[ArgFp]] %[[ArgBar]] +; CHECK: OpFunctionPointerCallINTEL %[[TyInt64]] %[[ArgBar]] %[[ArgFp]] %[[ArgData]] +; CHECK: OpReturn +; CHECK: OpFunctionEnd + +target triple = "spir64-unknown-unknown" VyacheslavLevytskyy wrote: The same as above, I guess we don't need this line. https://github.com/llvm/llvm-project/pull/89796 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Refine invalidation caused by `fread` (PR #93408)
@@ -0,0 +1,412 @@ +// RUN: %clang_analyze_cc1 -verify %s \ +// RUN: -triple x86_64-linux-gnu \ +// RUN: -analyzer-checker=core,unix.Stream,alpha.security.taint \ +// RUN: -analyzer-checker=debug.ExprInspection + +#include "Inputs/system-header-simulator-for-simple-stream.h" + +#define EOF (-1) + +void clang_analyzer_dump(int); +void clang_analyzer_isTainted(int); +void clang_analyzer_warnIfReached(void); + +// A stream is only tracked by StreamChecker if it results from a call to "fopen". +// Otherwise, there is no specific modelling of "fread". +void untracked_stream(FILE *fp) { + char c; + if (1 == fread(&c, 1, 1, fp)) { +char p = c; // Unknown value but not garbage and not modeled by checker. + } else { +char p = c; // Possibly indeterminate value but not modeled by checker. + } +} + +void fgetc_props_taint(void) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +int c = fgetc(fp); // c is tainted. +if (c != EOF) { + clang_analyzer_isTainted(c); // expected-warning{{YES}} +} +fclose(fp); + } +} + +void fread_props_taint(void) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +char buffer[10]; +int c = fread(buffer, 1, 10, fp); // c is tainted. +if (c != 10) { + // If the read failed, then the number of bytes successfully read should be tainted. + clang_analyzer_isTainted(c); // expected-warning{{YES}} +} +fclose(fp); + } +} + +void read_one_byte1(void) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +char c; +if (1 == fread(&c, 1, 1, fp)) { + char p = c; // Unknown value but not garbage. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} else { + char p = c; // Possibly indeterminate value but not modeled by checker. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} +fclose(fp); + } +} + +void read_one_byte2(char *buffer) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +if (1 == fread(buffer, 1, 1, fp)) { + char p = buffer[0]; // Unknown value but not garbage. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} else { + char p = buffer[0]; // Possibly indeterminate value but not modeled by checker. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} +fclose(fp); + } +} + +void read_one_byte3(char *buffer) { + buffer[1] = 10; + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +// buffer[1] is not mutated by fread and remains not tainted. +fread(buffer, 1, 1, fp); +char p = buffer[1]; +clang_analyzer_isTainted(p); // expected-warning{{NO}} +clang_analyzer_dump(buffer[1]); // expected-warning{{10 S32b}} +fclose(fp); + } +} + +void read_many_bytes(char *buffer) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +if (42 == fread(buffer, 1, 42, fp)) { + char p = buffer[0]; // Unknown value but not garbage. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} else { + char p = buffer[0]; // Possibly indeterminate value but not modeled. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} +fclose(fp); + } +} + +void random_access_write1(int index) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +long c[4]; +int success = 2 == fread(c + 1, sizeof(long), 2, fp); + +switch (index) { +case 0: + // c[0] is not mutated by fread. + if (success) { +char p = c[0]; // expected-warning {{Assigned value is garbage or undefined}} We kept the first byte intact. + } else { +char p = c[0]; // expected-warning {{Assigned value is garbage or undefined}} We kept the first byte intact. + } + break; + +case 1: + if (success) { +// Unknown value but not garbage. +clang_analyzer_isTainted(c[1]); // expected-warning {{YES}} +clang_analyzer_dump(c[1]); // expected-warning {{conj_}} + } else { +// Possibly indeterminate value but not modeled. +clang_analyzer_isTainted(c[1]); // expected-warning {{YES}} +clang_analyzer_dump(c[1]); // expected-warning {{conj_}} + } + break; + +case 2: + if (success) { +long p = c[2]; // Unknown value but not garbage. +// FIXME: Taint analysis only marks the first byte of a memory region. See getPointeeOf in GenericTaintChecker.cpp. +clang_analyzer_isTainted(c[2]); // expected-warning {{NO}} +clang_analyzer_dump(c[2]); // expected-warning {{conj_}} + } else { +// Possibly indeterminate value but not modeled. +clang_analyzer_isTainted(c[2]); // expected-warning {{NO}} // FIXME: See above. +clang_analyzer_dump(c[2]); // expected-warning {{conj_}} + } + break; + +case 3: + // c[3] is not mutated by fread. + if (success) { +long p = c[3]; // expected-warning {{Assigned value is garbage or undefined}} + } else { +long p = c[3]; // ex
[clang] [llvm] [clang][SPIR-V] Add support for AMDGCN flavoured SPIRV (PR #89796)
@@ -0,0 +1,35 @@ +; RUN: llc -O0 -mtriple=spirv64-amd-amdhsa --spirv-ext=+SPV_INTEL_function_pointers %s -o - | FileCheck %s +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-amd-amdhsa %s -o - -filetype=obj | spirv-val %} + +; CHECK-DAG: OpCapability Int8 +; CHECK-DAG: OpCapability GenericPointer +; CHECK-DAG: OpCapability FunctionPointersINTEL +; CHECK-DAG: OpCapability Int64 +; CHECK: OpExtension "SPV_INTEL_function_pointers" +; CHECK-DAG: %[[TyInt8:.*]] = OpTypeInt 8 0 +; CHECK-DAG: %[[TyVoid:.*]] = OpTypeVoid +; CHECK-DAG: %[[TyFloat32:.*]] = OpTypeFloat 32 +; CHECK-DAG: %[[TyInt64:.*]] = OpTypeInt 64 0 +; CHECK-DAG: %[[TyPtrInt8:.*]] = OpTypePointer Generic %[[TyInt8]] +; CHECK-DAG: %[[TyFunFp:.*]] = OpTypeFunction %[[TyFloat32]] %[[TyPtrInt8]] +; CHECK-DAG: %[[TyFunBar:.*]] = OpTypeFunction %[[TyInt64]] %[[TyPtrInt8]] %[[TyPtrInt8]] +; CHECK-DAG: %[[TyPtrFunFp:.*]] = OpTypePointer Function %[[TyFunFp]] +; CHECK-DAG: %[[TyPtrFunBar:.*]] = OpTypePointer Function %[[TyFunBar]] +; CHECK-DAG: %[[TyFunTest:.*]] = OpTypeFunction %[[TyVoid]] %[[TyPtrInt8]] %[[TyPtrInt8]] %[[TyPtrInt8]] +; CHECK: %[[FunTest:.*]] = OpFunction %[[TyVoid]] None %[[TyFunTest]] +; CHECK: %[[ArgFp:.*]] = OpFunctionParameter %[[TyPtrInt8]] +; CHECK: %[[ArgData:.*]] = OpFunctionParameter %[[TyPtrInt8]] +; CHECK: %[[ArgBar:.*]] = OpFunctionParameter %[[TyPtrInt8]] +; CHECK: OpFunctionPointerCallINTEL %[[TyFloat32]] %[[ArgFp]] %[[ArgBar]] +; CHECK: OpFunctionPointerCallINTEL %[[TyInt64]] %[[ArgBar]] %[[ArgFp]] %[[ArgData]] +; CHECK: OpReturn +; CHECK: OpFunctionEnd + +target triple = "spir64-unknown-unknown" + +define spir_kernel void @test(ptr addrspace(4) %fp, ptr addrspace(4) %data, ptr addrspace(4) %bar) { +entry: + %0 = call spir_func addrspace(4) float %fp(ptr addrspace(4) %bar) + %1 = call spir_func addrspace(4) i64 %bar(ptr addrspace(4) %fp, ptr addrspace(4) %data) + ret void +} VyacheslavLevytskyy wrote: I have a general suggestion, if I may, about those two function pointers tests. Neither the extension itself is perfect, nor its current implementation in SPIR-V Backend. About a half of Khronos Translator test cases for the function pointers extension crash when running with our SPIR-V Backend implementation, and this is a near to-do item in our development plans. Giving all these, probably it's better to freeze in tests as little of function pointers implementation logics as it's possible -- until the implementation is completed in full and all Khronos Translator test cases are successful. In terms of this PR this means that probably it's better to strip those 2 tests of details whenever this is possible, unless you consider each existing CHECK in those tests important. https://github.com/llvm/llvm-project/pull/89796 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [PowerPC] Support -mno-red-zone option (PR #94581)
chenzheng1030 wrote: > No. `-disable-red-zone` does nothing but add `noredzone` IR attribute to > functions. We need to add cases to test for `noredzone` behavior on PPC (arm > and x86 have). Yeah, go ahead to add some backend tests first to make sure we have good functionality for `noredzone` attribute. Thanks. https://github.com/llvm/llvm-project/pull/94581 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [AArch64] Decouple feature dependency expansion. (PR #94279)
davemgreen wrote: Yeah I had just seen that error message before you edited your comment. There are some examples of neon I found in a quick search, which were presumably added for AArch32: https://github.com/aaru-dps/Aaru.Checksums.Native/blob/bd5051ce181b225a7662bfb764ebcc5cbe7542b2/simd.h#L112 https://github.com/mooch443/commons/blob/30dc797430968831959d77d7f2503cec3518a13a/common/misc/PVBlob.cpp#L385 I'm not sure if that is reason enough to still support it. But like I said, if I try this patch locally then `target("neon")` seems to be accepted fine (no errors). It is the same for other features like `target("fullfp16")`, which seem to enable `+fullfp16` in the backend. `"noneon"` is no longer accepted, which might be fine as I don't believe negative features are commonly used. (For aarch64 from a baseline of armv8 they are mostly additive. They are likely to become more common going forward but new users can use the "right" attribute names). https://github.com/llvm/llvm-project/pull/94279 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] f1e78f7 - [clang][Interp] Handle lvalue APValues in visitAPValueInitializer()
Author: Timm Bäder Date: 2024-06-06T10:24:26+02:00 New Revision: f1e78f776908f2bc1759eae25381f576f62728a2 URL: https://github.com/llvm/llvm-project/commit/f1e78f776908f2bc1759eae25381f576f62728a2 DIFF: https://github.com/llvm/llvm-project/commit/f1e78f776908f2bc1759eae25381f576f62728a2.diff LOG: [clang][Interp] Handle lvalue APValues in visitAPValueInitializer() Added: Modified: clang/lib/AST/Interp/ByteCodeExprGen.cpp clang/test/CodeGenCXX/template-param-objects-linkage.cpp Removed: diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 3671c41ae7039..ea259639dace7 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -3188,7 +3188,7 @@ bool ByteCodeExprGen::visitAPValueInitializer(const APValue &Val, const APValue &F = Val.getStructField(I); const Record::Field *RF = R->getField(I); - if (F.isInt()) { + if (F.isInt() || F.isLValue()) { PrimType T = classifyPrim(RF->Decl->getType()); if (!this->visitAPValue(F, T, E)) return false; diff --git a/clang/test/CodeGenCXX/template-param-objects-linkage.cpp b/clang/test/CodeGenCXX/template-param-objects-linkage.cpp index 63e7d8c646869..9c148ed83753d 100644 --- a/clang/test/CodeGenCXX/template-param-objects-linkage.cpp +++ b/clang/test/CodeGenCXX/template-param-objects-linkage.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++20 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++20 %s -emit-llvm -o - -fexperimental-new-constant-interpreter | FileCheck %s struct S { char buf[32]; }; template constexpr const char* f() { return s.buf; } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libclc] [llvm] [AMDGPU] Add a new target gfx1152 (PR #94534)
@@ -1534,6 +1534,12 @@ def FeatureISAVersion11_5_1 : FeatureSet< FeatureVGPRSingleUseHintInsts, Feature1_5xVGPRs])>; +def FeatureISAVersion11_5_2 : FeatureSet< jayfoad wrote: I don't have a good answer to this except "it's what we normally do". Other parts of the software stack (kernel drivers etc) need to distinguish gfx1150 from gfx1152, and I guess they don't want to map "gfx1152" -> "gfx1150" before invoking the compiler. Also, it will make it easier for us to implement gfx1152-specific optimizations and workarounds in future if there are any. https://github.com/llvm/llvm-project/pull/94534 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Refine invalidation caused by `fread` (PR #93408)
@@ -0,0 +1,412 @@ +// RUN: %clang_analyze_cc1 -verify %s \ +// RUN: -triple x86_64-linux-gnu \ +// RUN: -analyzer-checker=core,unix.Stream,alpha.security.taint \ +// RUN: -analyzer-checker=debug.ExprInspection + +#include "Inputs/system-header-simulator-for-simple-stream.h" + +#define EOF (-1) + +void clang_analyzer_dump(int); +void clang_analyzer_isTainted(int); +void clang_analyzer_warnIfReached(void); + +// A stream is only tracked by StreamChecker if it results from a call to "fopen". +// Otherwise, there is no specific modelling of "fread". +void untracked_stream(FILE *fp) { + char c; + if (1 == fread(&c, 1, 1, fp)) { +char p = c; // Unknown value but not garbage and not modeled by checker. + } else { +char p = c; // Possibly indeterminate value but not modeled by checker. + } +} + +void fgetc_props_taint(void) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +int c = fgetc(fp); // c is tainted. +if (c != EOF) { + clang_analyzer_isTainted(c); // expected-warning{{YES}} +} +fclose(fp); + } +} + +void fread_props_taint(void) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +char buffer[10]; +int c = fread(buffer, 1, 10, fp); // c is tainted. +if (c != 10) { + // If the read failed, then the number of bytes successfully read should be tainted. + clang_analyzer_isTainted(c); // expected-warning{{YES}} +} +fclose(fp); + } +} + +void read_one_byte1(void) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +char c; +if (1 == fread(&c, 1, 1, fp)) { + char p = c; // Unknown value but not garbage. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} else { + char p = c; // Possibly indeterminate value but not modeled by checker. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} +fclose(fp); + } +} + +void read_one_byte2(char *buffer) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +if (1 == fread(buffer, 1, 1, fp)) { + char p = buffer[0]; // Unknown value but not garbage. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} else { + char p = buffer[0]; // Possibly indeterminate value but not modeled by checker. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} +fclose(fp); + } +} + +void read_one_byte3(char *buffer) { + buffer[1] = 10; + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +// buffer[1] is not mutated by fread and remains not tainted. +fread(buffer, 1, 1, fp); +char p = buffer[1]; +clang_analyzer_isTainted(p); // expected-warning{{NO}} +clang_analyzer_dump(buffer[1]); // expected-warning{{10 S32b}} +fclose(fp); + } +} + +void read_many_bytes(char *buffer) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +if (42 == fread(buffer, 1, 42, fp)) { + char p = buffer[0]; // Unknown value but not garbage. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} else { + char p = buffer[0]; // Possibly indeterminate value but not modeled. + clang_analyzer_isTainted(p); // expected-warning{{YES}} +} +fclose(fp); + } +} + +void random_access_write1(int index) { + FILE *fp = fopen("/home/test", "rb+"); + if (fp) { +long c[4]; +int success = 2 == fread(c + 1, sizeof(long), 2, fp); + +switch (index) { +case 0: + // c[0] is not mutated by fread. + if (success) { +char p = c[0]; // expected-warning {{Assigned value is garbage or undefined}} We kept the first byte intact. + } else { +char p = c[0]; // expected-warning {{Assigned value is garbage or undefined}} We kept the first byte intact. + } + break; + +case 1: + if (success) { +// Unknown value but not garbage. +clang_analyzer_isTainted(c[1]); // expected-warning {{YES}} +clang_analyzer_dump(c[1]); // expected-warning {{conj_}} + } else { +// Possibly indeterminate value but not modeled. +clang_analyzer_isTainted(c[1]); // expected-warning {{YES}} +clang_analyzer_dump(c[1]); // expected-warning {{conj_}} + } + break; + +case 2: + if (success) { +long p = c[2]; // Unknown value but not garbage. +// FIXME: Taint analysis only marks the first byte of a memory region. See getPointeeOf in GenericTaintChecker.cpp. +clang_analyzer_isTainted(c[2]); // expected-warning {{NO}} +clang_analyzer_dump(c[2]); // expected-warning {{conj_}} + } else { +// Possibly indeterminate value but not modeled. +clang_analyzer_isTainted(c[2]); // expected-warning {{NO}} // FIXME: See above. +clang_analyzer_dump(c[2]); // expected-warning {{conj_}} + } + break; + +case 3: + // c[3] is not mutated by fread. + if (success) { +long p = c[3]; // expected-warning {{Assigned value is garbage or undefined}} + } else { +long p = c[3]; // ex
[clang] [libclc] [llvm] [AMDGPU] Add a new target gfx1152 (PR #94534)
https://github.com/jayfoad approved this pull request. LGTM. Could also update `flang/cmake/modules/AddFlangOffloadRuntime.cmake` but I don't really know if it's our responsibility to update Flang. https://github.com/llvm/llvm-project/pull/94534 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Remove redundant LINK_LIBS (PR #94588)
https://github.com/nikic created https://github.com/llvm/llvm-project/pull/94588 clangAnalysis is already being pulled in via clang_target_link_libraries(). Also listing it in LINK_LIBS means that we'll link both against the static libraries and the shared libclang-cpp.so library if CLANG_LINK_CLANG_DYLIB is enabled, and waste time on unnecessary LTO. >From b4dda7214c4c6431c9f978296f68b494c4fc7b68 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 6 Jun 2024 10:25:25 +0200 Subject: [PATCH] [clang-tidy] Remove redundant LINK_LIBS clangAnalysis is already being pulled in via clang_target_link_libraries(). Also listing it in LINK_LIBS means that we'll link both against the static libraries and the shared libclang-cpp.so library if CLANG_LINK_CLANG_DYLIB is enabled, and waste time on unnecessary LTO. --- clang-tools-extra/clang-tidy/misc/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt index 35e29b9a7d13..36fcd8fc1b27 100644 --- a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt @@ -43,7 +43,6 @@ add_clang_library(clangTidyMiscModule UseAnonymousNamespaceCheck.cpp LINK_LIBS - clangAnalysis clangTidy clangTidyUtils ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Remove redundant LINK_LIBS (PR #94588)
llvmbot wrote: @llvm/pr-subscribers-clang-tidy Author: Nikita Popov (nikic) Changes clangAnalysis is already being pulled in via clang_target_link_libraries(). Also listing it in LINK_LIBS means that we'll link both against the static libraries and the shared libclang-cpp.so library if CLANG_LINK_CLANG_DYLIB is enabled, and waste time on unnecessary LTO. --- Full diff: https://github.com/llvm/llvm-project/pull/94588.diff 1 Files Affected: - (modified) clang-tools-extra/clang-tidy/misc/CMakeLists.txt (-1) ``diff diff --git a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt index 35e29b9a7d136..36fcd8fc1b277 100644 --- a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt @@ -43,7 +43,6 @@ add_clang_library(clangTidyMiscModule UseAnonymousNamespaceCheck.cpp LINK_LIBS - clangAnalysis clangTidy clangTidyUtils `` https://github.com/llvm/llvm-project/pull/94588 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [cmake] Respect CLANG_LINK_CLANG_DYLIB for objlibs (PR #93454)
https://github.com/nikic updated https://github.com/llvm/llvm-project/pull/93454 >From b0bcd36b62a93e7d8bd0f7f01e857ce9aa7544c2 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 27 May 2024 11:56:41 +0200 Subject: [PATCH 1/2] [cmake] Respect CLANG_LINK_CLANG_DYLIB for objlibs add_clang_library() will create a library clangFoo that depends on objlib obj.clangFoo. Then clang_target_link_libraries() will add a clang-cpp dependency to clangFoo, but obj.clangFoo will instead get dependencies on the individual clangXYZ libraries, instead of the shared object. The final outcome is that we will link both the static libraries and the shared object, leading to an increase in binary size and link times (when using LTO). Make sure we use the same logic for the obj and non-obj libs. --- clang/cmake/modules/AddClang.cmake | 10 ++ 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/clang/cmake/modules/AddClang.cmake b/clang/cmake/modules/AddClang.cmake index a5ef639187d9..534c7b84ecfb 100644 --- a/clang/cmake/modules/AddClang.cmake +++ b/clang/cmake/modules/AddClang.cmake @@ -194,10 +194,6 @@ macro(add_clang_symlink name dest) endmacro() function(clang_target_link_libraries target type) - if (TARGET obj.${target}) -target_link_libraries(obj.${target} ${ARGN}) - endif() - get_property(LLVM_DRIVER_TOOLS GLOBAL PROPERTY LLVM_DRIVER_TOOLS) if(LLVM_TOOL_LLVM_DRIVER_BUILD AND ${target} IN_LIST LLVM_DRIVER_TOOLS) set(target llvm-driver) @@ -205,7 +201,13 @@ function(clang_target_link_libraries target type) if (CLANG_LINK_CLANG_DYLIB) target_link_libraries(${target} ${type} clang-cpp) +if (TARGET obj.${target}) + target_link_libraries(obj.${target} clang-cpp) +endif() else() target_link_libraries(${target} ${type} ${ARGN}) +if (TARGET obj.${target}) + target_link_libraries(obj.${target} ${ARGN}) +endif() endif() endfunction() >From 1cc7f9a4dc8d406886188797858e314f2d7634c6 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 6 Jun 2024 10:05:35 +0200 Subject: [PATCH 2/2] Use INTERFACE dep --- clang/cmake/modules/AddClang.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/cmake/modules/AddClang.cmake b/clang/cmake/modules/AddClang.cmake index 534c7b84ecfb..2528c16a09e5 100644 --- a/clang/cmake/modules/AddClang.cmake +++ b/clang/cmake/modules/AddClang.cmake @@ -202,12 +202,12 @@ function(clang_target_link_libraries target type) if (CLANG_LINK_CLANG_DYLIB) target_link_libraries(${target} ${type} clang-cpp) if (TARGET obj.${target}) - target_link_libraries(obj.${target} clang-cpp) + target_link_libraries(obj.${target} INTERFACE clang-cpp) endif() else() target_link_libraries(${target} ${type} ${ARGN}) if (TARGET obj.${target}) - target_link_libraries(obj.${target} ${ARGN}) + target_link_libraries(obj.${target} INTERFACE ${ARGN}) endif() endif() endfunction() ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 7091dfc - [clang-repl] Lay the foundation of pretty printing for C. (#89811)
Author: Vassil Vassilev Date: 2024-06-06T11:49:10+03:00 New Revision: 7091dfc0e49b8c79f9e1daf6ab0ca0e65f30f347 URL: https://github.com/llvm/llvm-project/commit/7091dfc0e49b8c79f9e1daf6ab0ca0e65f30f347 DIFF: https://github.com/llvm/llvm-project/commit/7091dfc0e49b8c79f9e1daf6ab0ca0e65f30f347.diff LOG: [clang-repl] Lay the foundation of pretty printing for C. (#89811) Added: clang/test/Interpreter/pretty-print.c Modified: clang/lib/Interpreter/Interpreter.cpp clang/lib/Parse/ParseStmt.cpp Removed: diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index 683f87e8c8c7..7a9527891427 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -42,6 +42,9 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TargetParser/Host.h" + +#include + using namespace clang; // FIXME: Figure out how to unify with namespace init_convenience from @@ -270,14 +273,10 @@ Interpreter::~Interpreter() { // can't find the precise resource directory in unittests so we have to hard // code them. const char *const Runtimes = R"( +#define __CLANG_REPL__ 1 #ifdef __cplusplus +#define EXTERN_C extern "C" void *__clang_Interpreter_SetValueWithAlloc(void*, void*, void*); -void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*); -void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, void*); -void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, float); -void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, double); -void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, long double); -void __clang_Interpreter_SetValueNoAlloc(void*,void*,void*,unsigned long long); struct __clang_Interpreter_NewTag{} __ci_newtag; void* operator new(__SIZE_TYPE__, void* __p, __clang_Interpreter_NewTag) noexcept; template @@ -289,7 +288,11 @@ const char *const Runtimes = R"( void __clang_Interpreter_SetValueCopyArr(const T (*Src)[N], void* Placement, unsigned long Size) { __clang_Interpreter_SetValueCopyArr(Src[0], Placement, Size); } +#else +#define EXTERN_C extern #endif // __cplusplus + + EXTERN_C void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, ...); )"; llvm::Expected> @@ -588,15 +591,17 @@ std::unique_ptr Interpreter::FindRuntimeInterface() { if (!LookupInterface(ValuePrintingInfo[NoAlloc], MagicRuntimeInterface[NoAlloc])) return nullptr; - if (!LookupInterface(ValuePrintingInfo[WithAlloc], - MagicRuntimeInterface[WithAlloc])) -return nullptr; - if (!LookupInterface(ValuePrintingInfo[CopyArray], - MagicRuntimeInterface[CopyArray])) -return nullptr; - if (!LookupInterface(ValuePrintingInfo[NewTag], - MagicRuntimeInterface[NewTag])) -return nullptr; + if (Ctx.getLangOpts().CPlusPlus) { +if (!LookupInterface(ValuePrintingInfo[WithAlloc], + MagicRuntimeInterface[WithAlloc])) + return nullptr; +if (!LookupInterface(ValuePrintingInfo[CopyArray], + MagicRuntimeInterface[CopyArray])) + return nullptr; +if (!LookupInterface(ValuePrintingInfo[NewTag], + MagicRuntimeInterface[NewTag])) + return nullptr; + } return createInProcessRuntimeInterfaceBuilder(*this, Ctx, S); } @@ -855,69 +860,81 @@ __clang_Interpreter_SetValueWithAlloc(void *This, void *OutVal, return VRef.getPtr(); } -// Pointers, lvalue struct that can take as a reference. -REPL_EXTERNAL_VISIBILITY void -__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, -void *Val) { +extern "C" void REPL_EXTERNAL_VISIBILITY __clang_Interpreter_SetValueNoAlloc( +void *This, void *OutVal, void *OpaqueType, ...) { Value &VRef = *(Value *)OutVal; - VRef = Value(static_cast(This), OpaqueType); - VRef.setPtr(Val); -} + Interpreter *I = static_cast(This); + VRef = Value(I, OpaqueType); + if (VRef.isVoid()) +return; -REPL_EXTERNAL_VISIBILITY void -__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, -void *OpaqueType) { - Value &VRef = *(Value *)OutVal; - VRef = Value(static_cast(This), OpaqueType); -} + va_list args; + va_start(args, /*last named param*/ OpaqueType); -static void SetValueDataBasedOnQualType(Value &V, unsigned long long Data) { - QualType QT = V.getType(); - if (const auto *ET = QT->getAs()) -QT = ET->getDecl()->getIntegerType(); - - switch (QT->castAs()->getKind()) { - default: -llvm_unreachable("unknown type kind!"); -#define X(type, name) \ - case BuiltinType::name:
[clang] [clang-repl] Lay the foundation of pretty printing for C. (PR #89811)
https://github.com/vgvassilev closed https://github.com/llvm/llvm-project/pull/89811 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][AMDGPU] Add builtins for instrinsic `llvm.amdgcn.raw.buffer.store` (PR #94576)
jayfoad wrote: Is there really a good use case for this? Can you use regular stores to addrspace(7) instead? @krzysz00 Also, do you really need a separate builtin for every legal type, or is there some way they can be type-overloaded? https://github.com/llvm/llvm-project/pull/94576 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [RISCV] Add processor definition for SpacemiT-X60 (PR #94564)
zqb-all wrote: Need to add zicond, which is not in RVA22S64Features https://github.com/llvm/llvm-project/pull/94564 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][AMDGPU] Add builtins for instrinsic `llvm.amdgcn.raw.buffer.store` (PR #94576)
arsenm wrote: > Is there really a good use case for this? Can you use regular stores to > addrspace(7) instead? @krzysz00 I see these regularly used via inline asm in various ML code. We need to expose these in some way to stop people from doing that > > Also, do you really need a separate builtin for every legal type, or is there > some way they can be type-overloaded? Yes, I imagined we would handle images similar to the elementwise intrinsics. However, I don't think that approach works for loads. If we have to have overloads for loads, we probably should mirror it for stores. I think it makes more sense to solve the issue for the load case before the stores. They're a bit more complicated because you have the sign vs. zero extended cases to consider, and the overload would be on the return type https://github.com/llvm/llvm-project/pull/94576 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix spurious availability warning (PR #94377)
https://github.com/Xazax-hun ready_for_review https://github.com/llvm/llvm-project/pull/94377 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][AMDGPU] Add builtins for instrinsic `llvm.amdgcn.raw.buffer.store` (PR #94576)
@@ -0,0 +1,264 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// REQUIRES: amdgpu-registered-target +// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu verde -emit-llvm -o - %s | FileCheck %s --check-prefixes=VERDE +// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu tonga -emit-llvm -o - %s | FileCheck %s --check-prefixes=GFX8 +// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx1100 -emit-llvm -o - %s | FileCheck %s --check-prefixes=GFX11 + +#pragma OPENCL EXTENSION cl_khr_fp16 : enable + +typedef short v2i16 __attribute__((ext_vector_type(2))); +typedef int v2i32 __attribute__((ext_vector_type(2))); +typedef half v2f16 __attribute__((ext_vector_type(2))); +typedef float v2f32 __attribute__((ext_vector_type(2))); +typedef short v4i16 __attribute__((ext_vector_type(4))); +typedef int v4i32 __attribute__((ext_vector_type(4))); +typedef half v4f16 __attribute__((ext_vector_type(4))); +typedef float v4f32 __attribute__((ext_vector_type(4))); + +// VERDE-LABEL: @test_amdgcn_raw_buffer_store_i8( +// VERDE-NEXT: entry: +// VERDE-NEXT:tail call void @llvm.amdgcn.raw.buffer.store.i8(i8 [[VDATA:%.*]], <4 x i32> [[RSRC:%.*]], i32 0, i32 0, i32 0) +// VERDE-NEXT:ret void +// +// GFX8-LABEL: @test_amdgcn_raw_buffer_store_i8( +// GFX8-NEXT: entry: +// GFX8-NEXT:tail call void @llvm.amdgcn.raw.buffer.store.i8(i8 [[VDATA:%.*]], <4 x i32> [[RSRC:%.*]], i32 0, i32 0, i32 0) +// GFX8-NEXT:ret void +// +// GFX11-LABEL: @test_amdgcn_raw_buffer_store_i8( +// GFX11-NEXT: entry: +// GFX11-NEXT:tail call void @llvm.amdgcn.raw.buffer.store.i8(i8 [[VDATA:%.*]], <4 x i32> [[RSRC:%.*]], i32 0, i32 0, i32 0) +// GFX11-NEXT:ret void +// +void test_amdgcn_raw_buffer_store_i8(char vdata, v4i32 rsrc) { arsenm wrote: We are trying to move to using real pointers (i.e. use llvm.amdgcn.raw.ptr.buffer.store instead of llvm.amdgcn.raw.buffer.store) https://github.com/llvm/llvm-project/pull/94576 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix spurious availability warning (PR #94377)
llvmbot wrote: @llvm/pr-subscribers-clang Author: Gábor Horváth (Xazax-hun) Changes The availability attributes are stored on the function declarations. The code was looking for them in the function template declarations. This resulted in spuriously diagnosing availablity issues in contexts that are not available. --- Full diff: https://github.com/llvm/llvm-project/pull/94377.diff 3 Files Affected: - (modified) clang/include/clang/Sema/Initialization.h (+1-1) - (modified) clang/lib/Sema/SemaAvailability.cpp (+5) - (added) clang/test/Sema/attr-availability-macosx.cpp (+17) ``diff diff --git a/clang/include/clang/Sema/Initialization.h b/clang/include/clang/Sema/Initialization.h index 2072cd8d1c3ef..f443e327eaf32 100644 --- a/clang/include/clang/Sema/Initialization.h +++ b/clang/include/clang/Sema/Initialization.h @@ -212,7 +212,7 @@ class alignas(8) InitializedEntity { struct C Capture; }; - InitializedEntity() {}; + InitializedEntity() {} /// Create the initialization entity for a variable. InitializedEntity(VarDecl *Var, EntityKind EK = EK_Variable) diff --git a/clang/lib/Sema/SemaAvailability.cpp b/clang/lib/Sema/SemaAvailability.cpp index 330cd602297d4..3e5f90b450367 100644 --- a/clang/lib/Sema/SemaAvailability.cpp +++ b/clang/lib/Sema/SemaAvailability.cpp @@ -12,6 +12,7 @@ #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/IdentifierTable.h" @@ -46,6 +47,10 @@ static const AvailabilityAttr *getAttrForPlatform(ASTContext &Context, // Check each AvailabilityAttr to find the one for this platform. // For multiple attributes with the same platform try to find one for this // environment. + // The attribute is always on the FunctionDecl, not on the + // FunctionTemplateDecl. + if (const auto *FTD = dyn_cast(D)) +D = FTD->getTemplatedDecl(); for (const auto *A : D->attrs()) { if (const auto *Avail = dyn_cast(A)) { // FIXME: this is copied from CheckAvailability. We should try to diff --git a/clang/test/Sema/attr-availability-macosx.cpp b/clang/test/Sema/attr-availability-macosx.cpp new file mode 100644 index 0..52f320d409281 --- /dev/null +++ b/clang/test/Sema/attr-availability-macosx.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 "-triple" "arm64-apple-macosx10.15" -fsyntax-only -verify %s + +__attribute__((availability(macos,introduced=11))) +inline bool try_acquire() { + return true; +} + +template +__attribute__((availability(macos,introduced=11))) +bool try_acquire_for(T duration) { // expected-note{{'try_acquire_for' has been marked as being introduced in macOS 11 here, but the deployment target is macOS 10.15}} + return try_acquire(); +} + +int main() { + try_acquire_for(1); // expected-warning{{'try_acquire_for' is only available on macOS 11 or newer}} + // expected-note@-1{{enclose 'try_acquire_for' in a __builtin_available check to silence this warning}} +} \ No newline at end of file `` https://github.com/llvm/llvm-project/pull/94377 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix spurious availability warning (PR #94377)
Xazax-hun wrote: Thos should fix the non-strict availability related repro from https://github.com/llvm/llvm-project/issues/40423 . It does not fix the strict case which is a separate codepath, so I did not mark this PR as fixing that bug report. https://github.com/llvm/llvm-project/pull/94377 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fixed grammatical error in "enum specifier" error msg #94443 (PR #94592)
https://github.com/kper created https://github.com/llvm/llvm-project/pull/94592 As discussed in #94443, this PR changes the wording to be more correct. >From 6ff1ec93e93e988b4e4fb2f490d5ea5a7d6e506a Mon Sep 17 00:00:00 2001 From: Kevin Per Date: Wed, 5 Jun 2024 18:45:10 + Subject: [PATCH] Fixed grammatical error in "enum specifier" error msg #94443 --- clang/include/clang/Basic/DiagnosticSemaKinds.td| 6 +++--- clang/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp | 4 ++-- .../CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp | 6 +++--- clang/test/CXX/drs/cwg2xx.cpp | 6 +++--- clang/test/CXX/drs/cwg4xx.cpp | 2 +- clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp | 2 +- clang/test/CXX/temp/temp.spec/no-body.cpp | 2 +- clang/test/SemaCXX/PR8755.cpp | 2 +- clang/test/SemaCXX/using-decl-templates.cpp | 2 +- clang/test/SemaTemplate/template-id-expr.cpp| 2 +- 10 files changed, 17 insertions(+), 17 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 1a117245a325e3..4f74f62374d8b0 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6088,9 +6088,9 @@ def err_redefinition_different_concept : Error< "redefinition of concept %0 with different template parameters or requirements">; def err_tag_reference_non_tag : Error< "%select{non-struct type|non-class type|non-union type|non-enum " - "type|typedef|type alias|template|type alias template|template " - "template argument}1 %0 cannot be referenced with a " - "%select{struct|interface|union|class|enum}2 specifier">; + "type|typedef|type alias|template|alias template|template " + "template argument}1 %0 cannot be referenced with the '" + "%select{struct|interface|union|class|enum}2' specifier">; def err_tag_reference_conflict : Error< "implicit declaration introduced by elaborated type conflicts with a " "%select{non-struct type|non-class type|non-union type|non-enum " diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp index a908518f02ea2e..c58cbfefc7997c 100644 --- a/clang/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp @@ -9,7 +9,7 @@ namespace test0 { typedef int A; // expected-note {{declared here}} int test() { - struct A a; // expected-error {{typedef 'A' cannot be referenced with a struct specifier}} + struct A a; // expected-error {{typedef 'A' cannot be referenced with the 'struct' specifier}} return a.foo; } } @@ -18,7 +18,7 @@ namespace test0 { template class A; // expected-note {{declared here}} int test() { - struct A a; // expected-error {{template 'A' cannot be referenced with a struct specifier}} + struct A a; // expected-error {{template 'A' cannot be referenced with the 'struct' specifier}} return a.foo; } } diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp index f3e79c0aae44a8..98c9b915c6ce9f 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp @@ -2,18 +2,18 @@ struct A { typedef int type; }; template using X = A; // expected-note {{declared here}} -struct X* p2; // expected-error {{type alias template 'X' cannot be referenced with a struct specifier}} +struct X* p2; // expected-error {{alias template 'X' cannot be referenced with the 'struct' specifier}} template using Id = T; // expected-note {{declared here}} template class F> struct Y { - struct F i; // expected-error {{type alias template 'Id' cannot be referenced with a struct specifier}} + struct F i; // expected-error {{alias template 'Id' cannot be referenced with the 'struct' specifier}} typename F::type j; // ok // FIXME: don't produce the diagnostic both for the definition and the instantiation. template using U = F; // expected-note 2{{declared here}} - struct Y::template U k; // expected-error 2{{type alias template 'U' cannot be referenced with a struct specifier}} + struct Y::template U k; // expected-error 2{{alias template 'U' cannot be referenced with the 'struct' specifier}} typename Y::template U l; // ok }; template struct Y; // expected-note {{requested here}} diff --git a/clang/test/CXX/drs/cwg2xx.cpp b/clang/test/CXX/drs/cwg2xx.cpp index 2b3131be33057a..99916dea9a9120 100644 --- a/clang/test/CXX/drs/cwg2xx.cpp +++ b/clang/test/CXX/drs/cwg2xx.cpp @@ -759,7 +759,7 @@ namespace cwg254 { // cwg254: 2.9 typedef typename T::type type; // ok even if this is a typedef-n
[clang] Fixed grammatical error in "enum specifier" error msg #94443 (PR #94592)
github-actions[bot] wrote: Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using `@` followed by their GitHub username. If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the [LLVM GitHub User Guide](https://llvm.org/docs/GitHub.html). You can also ask questions in a comment on this PR, on the [LLVM Discord](https://discord.com/invite/xS7Z362) or on the [forums](https://discourse.llvm.org/). https://github.com/llvm/llvm-project/pull/94592 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fixed grammatical error in "enum specifier" error msg #94443 (PR #94592)
llvmbot wrote: @llvm/pr-subscribers-clang Author: None (kper) Changes As discussed in #94443, this PR changes the wording to be more correct. --- Full diff: https://github.com/llvm/llvm-project/pull/94592.diff 10 Files Affected: - (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+3-3) - (modified) clang/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp (+2-2) - (modified) clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp (+3-3) - (modified) clang/test/CXX/drs/cwg2xx.cpp (+3-3) - (modified) clang/test/CXX/drs/cwg4xx.cpp (+1-1) - (modified) clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp (+1-1) - (modified) clang/test/CXX/temp/temp.spec/no-body.cpp (+1-1) - (modified) clang/test/SemaCXX/PR8755.cpp (+1-1) - (modified) clang/test/SemaCXX/using-decl-templates.cpp (+1-1) - (modified) clang/test/SemaTemplate/template-id-expr.cpp (+1-1) ``diff diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 1a117245a325e3..4f74f62374d8b0 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6088,9 +6088,9 @@ def err_redefinition_different_concept : Error< "redefinition of concept %0 with different template parameters or requirements">; def err_tag_reference_non_tag : Error< "%select{non-struct type|non-class type|non-union type|non-enum " - "type|typedef|type alias|template|type alias template|template " - "template argument}1 %0 cannot be referenced with a " - "%select{struct|interface|union|class|enum}2 specifier">; + "type|typedef|type alias|template|alias template|template " + "template argument}1 %0 cannot be referenced with the '" + "%select{struct|interface|union|class|enum}2' specifier">; def err_tag_reference_conflict : Error< "implicit declaration introduced by elaborated type conflicts with a " "%select{non-struct type|non-class type|non-union type|non-enum " diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp index a908518f02ea2e..c58cbfefc7997c 100644 --- a/clang/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp @@ -9,7 +9,7 @@ namespace test0 { typedef int A; // expected-note {{declared here}} int test() { - struct A a; // expected-error {{typedef 'A' cannot be referenced with a struct specifier}} + struct A a; // expected-error {{typedef 'A' cannot be referenced with the 'struct' specifier}} return a.foo; } } @@ -18,7 +18,7 @@ namespace test0 { template class A; // expected-note {{declared here}} int test() { - struct A a; // expected-error {{template 'A' cannot be referenced with a struct specifier}} + struct A a; // expected-error {{template 'A' cannot be referenced with the 'struct' specifier}} return a.foo; } } diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp index f3e79c0aae44a8..98c9b915c6ce9f 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp @@ -2,18 +2,18 @@ struct A { typedef int type; }; template using X = A; // expected-note {{declared here}} -struct X* p2; // expected-error {{type alias template 'X' cannot be referenced with a struct specifier}} +struct X* p2; // expected-error {{alias template 'X' cannot be referenced with the 'struct' specifier}} template using Id = T; // expected-note {{declared here}} template class F> struct Y { - struct F i; // expected-error {{type alias template 'Id' cannot be referenced with a struct specifier}} + struct F i; // expected-error {{alias template 'Id' cannot be referenced with the 'struct' specifier}} typename F::type j; // ok // FIXME: don't produce the diagnostic both for the definition and the instantiation. template using U = F; // expected-note 2{{declared here}} - struct Y::template U k; // expected-error 2{{type alias template 'U' cannot be referenced with a struct specifier}} + struct Y::template U k; // expected-error 2{{alias template 'U' cannot be referenced with the 'struct' specifier}} typename Y::template U l; // ok }; template struct Y; // expected-note {{requested here}} diff --git a/clang/test/CXX/drs/cwg2xx.cpp b/clang/test/CXX/drs/cwg2xx.cpp index 2b3131be33057a..99916dea9a9120 100644 --- a/clang/test/CXX/drs/cwg2xx.cpp +++ b/clang/test/CXX/drs/cwg2xx.cpp @@ -759,7 +759,7 @@ namespace cwg254 { // cwg254: 2.9 typedef typename T::type type; // ok even if this is a typedef-name, because // it's not an elaborated-type-specifier typedef struct T::type foo; -// expected-error@-1 {{typedef 'type' cannot be referenced with a str
[clang] [analyzer] Refine invalidation caused by `fread` (PR #93408)
@@ -907,6 +945,73 @@ void StreamChecker::preWrite(const FnDescription *Desc, const CallEvent &Call, C.addTransition(State); } +static std::optional getPointeeType(const MemRegion *R) { + if (!R) +return std::nullopt; + if (const auto *ER = dyn_cast(R)) +return ER->getElementType(); + if (const auto *TR = dyn_cast(R)) +return TR->getValueType(); + if (const auto *SR = dyn_cast(R)) +return SR->getPointeeStaticType(); + return std::nullopt; +} + +static std::optional getStartIndex(SValBuilder &SVB, + const MemRegion *R) { + if (!R) +return std::nullopt; + + auto Zero = [&SVB] { +BasicValueFactory &BVF = SVB.getBasicValueFactory(); +return nonloc::ConcreteInt(BVF.getIntValue(0, /*isUnsigned=*/false)); + }; + + if (const auto *ER = dyn_cast(R)) +return ER->getIndex(); + if (const auto *TR = dyn_cast(R)) +return Zero(); + if (const auto *SR = dyn_cast(R)) +return Zero(); + return std::nullopt; +} + +static ProgramStateRef +tryToInvalidateFReadBufferByElements(ProgramStateRef State, CheckerContext &C, + const CallEvent &Call, NonLoc SizeVal, + NonLoc NMembVal) { + // Try to invalidate the individual elements. + const auto *Buffer = + dyn_cast_or_null(Call.getArgSVal(0).getAsRegion()); + + std::optional ElemTy = getPointeeType(Buffer); + std::optional StartElementIndex = + getStartIndex(C.getSValBuilder(), Buffer); + + // Drop the outermost ElementRegion to get the buffer. + if (const auto *ER = dyn_cast_or_null(Buffer)) +Buffer = dyn_cast(ER->getSuperRegion()); + + std::optional CountVal = getKnownValue(State, NMembVal); + std::optional Size = getKnownValue(State, SizeVal); + std::optional StartIndexVal = + getKnownValue(State, StartElementIndex.value_or(UnknownVal())); + + if (ElemTy && CountVal && Size && StartIndexVal) { +int64_t NumBytesRead = Size.value() * CountVal.value(); +int64_t ElemSizeInChars = +C.getASTContext().getTypeSizeInChars(*ElemTy).getQuantity(); +bool DivisibleAccessSpan = (NumBytesRead % ElemSizeInChars) == 0; +int64_t NumElementsRead = NumBytesRead / ElemSizeInChars; +constexpr int MaxInvalidatedElementsLimit = 64; +if (DivisibleAccessSpan && NumElementsRead <= MaxInvalidatedElementsLimit) { steakhal wrote: Applied a patch to this code such that the last partial element is considered as a full access. This is indeed better than doing a fallback and invalidating the full buffer. Also modified the test to demonstrate this, but there is yet another bug in the current Store: If we read from a byte offset of an element, we still get unknown as a result: `int buffer[2] = {2,3}` then reading from `((char*)buffer)[1]` results in unknown. [Compiler explorer](https://godbolt.org/z/dTKGnYo9W). https://github.com/llvm/llvm-project/pull/93408 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix spurious availability warning (PR #94377)
https://github.com/Xazax-hun edited https://github.com/llvm/llvm-project/pull/94377 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [cmake] Respect CLANG_LINK_CLANG_DYLIB for objlibs (PR #93454)
nikic wrote: I suspect I may have misdiagnosed the issue, and the actual problem may be just https://github.com/llvm/llvm-project/pull/94588. I'll double check whether this change is necessary before landing. https://github.com/llvm/llvm-project/pull/93454 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Fix spurious non-strict availability warning (PR #94377)
https://github.com/Xazax-hun edited https://github.com/llvm/llvm-project/pull/94377 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Refine invalidation caused by `fread` (PR #93408)
https://github.com/steakhal updated https://github.com/llvm/llvm-project/pull/93408 Unicorn! · GitHub body { background-color: #f1f1f1; margin: 0; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; } .container { margin: 50px auto 40px auto; width: 600px; text-align: center; } a { color: #4183c4; text-decoration: none; } a:hover { text-decoration: underline; } h1 { letter-spacing: -1px; line-height: 60px; font-size: 60px; font-weight: 100; margin: 0px; text-shadow: 0 1px 0 #fff; } p { color: rgba(0, 0, 0, 0.5); margin: 10px 0 10px; font-size: 18px; font-weight: 200; line-height: 1.6em;} ul { list-style: none; margin: 25px 0; padding: 0; } li { display: table-cell; font-weight: bold; width: 1%; } .logo { display: inline-block; margin-top: 35px; } .logo-img-2x { display: none; } @media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and ( min--moz-device-pixel-ratio: 2), only screen and ( -o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { .logo-img-1x { display: none; } .logo-img-2x { display: inline-block; } } #suggestions { margin-top: 35px; color: #ccc; } #suggestions a { color: #66; font-weight: 200; font-size: 14px; margin: 0 10px; } We couldn't respond to your request in time. Sorry about that. Please try refreshing and contact us if the problem persists. https://github.com/contact";>Contact Support — https://www.githubstatus.com";>GitHub Status — https://twitter.com/githubstatus";>@githubstatus ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [analyzer] Refine invalidation caused by `fread` (PR #93408)
steakhal wrote: Addressed all the feedback. https://github.com/llvm/llvm-project/pull/93408 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] `doesNotMutateObject`: Handle calls to member functions … (PR #94362)
@@ -36,6 +36,111 @@ void extractNodesByIdTo(ArrayRef Matches, StringRef ID, Nodes.insert(Match.getNodeAs(ID)); } +// If `D` has a const-qualified overload with otherwise identical +// ref-qualifiers, returns that overload. +const CXXMethodDecl *findConstOverload(const CXXMethodDecl &D) { + assert(!D.isConst()); + + DeclContext::lookup_result lookup_result = + D.getParent()->lookup(D.getNameInfo().getName()); + if (lookup_result.isSingleResult()) { +// No overload. +return nullptr; + } + for (const Decl *overload : lookup_result) { +const CXXMethodDecl *candidate = dyn_cast(overload); +if (candidate && !candidate->isDeleted() && candidate->isConst() && +candidate->getRefQualifier() == D.getRefQualifier()) { legrosbuffle wrote: Overloading would be allowed in this case, but I think having a `const` overload with the same *parameter* types is enough to say that the use is immutable (not that the case when the return value is non-const and the object might be modified through the return value is caught by `(C)`). I've added a test to make this explicit (`weird_overload()`). That being said, your comment made me realize that we were not checking that the parameter types were the same. Done and added tests (`at(Tag1)`). Thanks :) https://github.com/llvm/llvm-project/pull/94362 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [ARM] r11 is reserved when using -mframe-chain=aapcs (PR #86951)
https://github.com/ostannard updated https://github.com/llvm/llvm-project/pull/86951 >From 1e141e80b0abf45f160c06f8eb39623df16434d8 Mon Sep 17 00:00:00 2001 From: Oliver Stannard Date: Thu, 6 Jun 2024 09:34:13 +0100 Subject: [PATCH 1/2] [IR] Add target-independent option to preserve frame-pointer register This adds a new value "reserved" to the "frame-pointer" function attribute. When this value is used, the frame pointer register must either be reserved, or updated to point to a new frame record, but must not be used for any other purpose. This is not yet supported by most targets, but will be used for the Arm -mframe-chain= option. --- clang/include/clang/Basic/CodeGenOptions.def | 2 +- clang/include/clang/Basic/CodeGenOptions.h | 3 +++ clang/include/clang/Driver/Options.td| 4 ++-- clang/lib/CodeGen/CGCall.cpp | 1 + clang/lib/CodeGen/CodeGenModule.cpp | 3 +++ clang/lib/Driver/ToolChains/Clang.cpp| 3 +++ llvm/docs/LangRef.rst| 6 +- llvm/include/llvm/Support/CodeGen.h | 2 +- llvm/include/llvm/Target/TargetOptions.h | 5 + llvm/lib/CodeGen/CommandFlags.cpp| 5 + llvm/lib/CodeGen/TargetOptionsImpl.cpp | 21 ++-- llvm/lib/IR/Function.cpp | 3 +++ llvm/lib/IR/Verifier.cpp | 2 +- 13 files changed, 52 insertions(+), 8 deletions(-) diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 07b0ca1691a67..7ffc40a00504f 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -61,7 +61,7 @@ CODEGENOPT(SeparateNamedSections, 1, 0) ///< Set for -fseparate-named-sections. CODEGENOPT(EnableAIXExtendedAltivecABI, 1, 0) ///< Set for -mabi=vec-extabi. Enables the extended Altivec ABI on AIX. CODEGENOPT(XCOFFReadOnlyPointers, 1, 0) ///< Set for -mxcoff-roptr. CODEGENOPT(AllTocData, 1, 0) ///< AIX -mtocdata -ENUM_CODEGENOPT(FramePointer, FramePointerKind, 2, FramePointerKind::None) /// frame-pointer: all,non-leaf,none +ENUM_CODEGENOPT(FramePointer, FramePointerKind, 2, FramePointerKind::None) /// frame-pointer: all,non-leaf,reserved,none CODEGENOPT(ClearASTBeforeBackend , 1, 0) ///< Free the AST before running backend code generation. Only works with -disable-free. CODEGENOPT(DisableFree , 1, 0) ///< Don't free memory. diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index 9469a424045bb..6887926cb34da 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -128,6 +128,7 @@ class CodeGenOptions : public CodeGenOptionsBase { enum class FramePointerKind { None,// Omit all frame pointers. +Reserved,// Maintain valid frame pointer chain. NonLeaf, // Keep non-leaf frame pointers. All, // Keep all frame pointers. }; @@ -136,6 +137,8 @@ class CodeGenOptions : public CodeGenOptionsBase { switch (Kind) { case FramePointerKind::None: return "none"; +case FramePointerKind::Reserved: + return "reserved"; case FramePointerKind::NonLeaf: return "non-leaf"; case FramePointerKind::All: diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 57f37c5023110..9b89b394cef52 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -7706,8 +7706,8 @@ def pic_is_pie : Flag<["-"], "pic-is-pie">, MarshallingInfoFlag>; def mframe_pointer_EQ : Joined<["-"], "mframe-pointer=">, - HelpText<"Specify which frame pointers to retain.">, Values<"all,non-leaf,none">, - NormalizedValuesScope<"CodeGenOptions::FramePointerKind">, NormalizedValues<["All", "NonLeaf", "None"]>, + HelpText<"Specify which frame pointers to retain.">, Values<"all,non-leaf,reserved,none">, + NormalizedValuesScope<"CodeGenOptions::FramePointerKind">, NormalizedValues<["All", "NonLeaf", "Reserved", "None"]>, MarshallingInfoEnum, "None">; diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 97449a5e51e73..65d82285b907b 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1917,6 +1917,7 @@ static void getTrivialDefaultFunctionAttributes( case CodeGenOptions::FramePointerKind::None: // This is the default behavior. break; +case CodeGenOptions::FramePointerKind::Reserved: case CodeGenOptions::FramePointerKind::NonLeaf: case CodeGenOptions::FramePointerKind::All: FuncAttrs.addAttribute("frame-pointer", diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index be7bf0b72dc0c..75b1449090389 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1328,6 +1328,9 @@ void CodeGenModule::Release() { case CodeGenOptions:
[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)
@@ -0,0 +1,81 @@ +//=== ModuleDependencyScanner.cpp *- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "ModuleDependencyScanner.h" +#include "support/Logger.h" + +namespace clang { +namespace clangd { + +std::optional +ModuleDependencyScanner::scan(PathRef FilePath) { + std::optional Cmd = CDB.getCompileCommand(FilePath); + + if (!Cmd) +return std::nullopt; + + using namespace clang::tooling::dependencies; + + llvm::SmallString<128> FilePathDir(FilePath); + llvm::sys::path::remove_filename(FilePathDir); + DependencyScanningTool ScanningTool(Service, TFS.view(FilePathDir)); + + llvm::Expected ScanningResult = + ScanningTool.getP1689ModuleDependencyFile(*Cmd, Cmd->Directory); + + if (auto E = ScanningResult.takeError()) { +log("Scanning modules dependencies for {0} failed: {1}", FilePath, +llvm::toString(std::move(E))); +return std::nullopt; + } + + ModuleDependencyInfo Result; + + if (ScanningResult->Provides) { +ModuleNameToSource[ScanningResult->Provides->ModuleName] = FilePath; ChuanqiXu9 wrote: > Are we really going into all this complexity to optimize the case of files > with no modular dependencies? Yes, this is primarily the reason why we delay it. > files with no modular dependencies is going to be so rare in practice This assumption is not true to me unless we're talking about the ecosystem 10+ years later. (There is a website (https://arewemodulesyet.org/) tracking the progress. Although its progress bar is almost a joke). Since programmers needs to refactor their code to use C++20 modules, we believe there will still be a lot of files unrelated to modules exists. Especially for headers. To make this more clear, currently, there are 2 ways to use modules. One is to use modules extensively and get rid of headers. Examples are https://github.com/infiniflow/infinity and https://github.com/davidstone/technical-machine, where we can see rare headers and almost all the files are related to modules. However, there are more projects are simply wrapped themselves with modules, so that the users can consume the library by including or by importing by their interest. (Or even importing in some .cc and including in some other .cc if the size of the code bases it too big). Most projects on the previous mentioned website uses this model. From the perspective, I think the assumption that modules-native (I called it) style won't take the place all over the world soon. > so having this extra mental load and requirements about an implementation > detail that doesn't bring much benefits in practice, and planned to be > stripped away is just too much for maintenance. Of course, since the first patch is not focus on performance and the design, I can drop it if you really don't like it. https://github.com/llvm/llvm-project/pull/66462 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)
@@ -740,6 +741,21 @@ DirectoryBasedGlobalCompilationDatabase::getProjectInfo(PathRef File) const { return Res->PI; } +std::shared_ptr +DirectoryBasedGlobalCompilationDatabase::getProjectModules(PathRef File) const { + CDBLookupRequest Req; + Req.FileName = File; + Req.ShouldBroadcast = false; + Req.FreshTime = Req.FreshTimeMissing = + std::chrono::steady_clock::time_point::min(); + auto Res = lookupCDB(Req); + if (!Res) +return {}; + return ProjectModules::create( + ProjectModules::ProjectModulesKind::ScanningAllFiles, + Res->CDB->getAllFiles(), *this, Opts.TFS); ChuanqiXu9 wrote: Done by following other comments. https://github.com/llvm/llvm-project/pull/66462 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)
@@ -222,6 +222,9 @@ class TUScheduler { /// Cache (large) preamble data in RAM rather than temporary files on disk. bool StorePreamblesInMemory = false; +/// Enable experimental support for modules. +bool ExperimentalModulesSupport = false; ChuanqiXu9 wrote: Done https://github.com/llvm/llvm-project/pull/66462 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)
@@ -42,6 +42,8 @@ namespace clang { namespace clangd { + +class ModulesBuilder; ChuanqiXu9 wrote: Done https://github.com/llvm/llvm-project/pull/66462 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)
ChuanqiXu9 wrote: Done https://github.com/llvm/llvm-project/pull/66462 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)
@@ -0,0 +1,339 @@ +//===- ModulesBuilder.cpp *- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "ModulesBuilder.h" +#include "PrerequisiteModules.h" +#include "support/Logger.h" + +#include "clang/Frontend/FrontendAction.h" +#include "clang/Frontend/FrontendActions.h" + +namespace clang { +namespace clangd { + +namespace { + +/// Get or create a path to store module files. Generally it should be: +/// +/// project_root/.cache/clangd/module_files/{RequiredPrefixDir}/. +/// +/// \param MainFile is used to get the root of the project from global +/// compilation database. \param RequiredPrefixDir is used to get the user +/// defined prefix for module files. This is useful when we want to seperate +/// module files. e.g., we want to build module files for the same module unit +/// `a.cppm` with 2 different users `b.cpp` and `c.cpp` and we don't want the +/// module file for `b.cpp` be conflict with the module files for `c.cpp`. Then +/// we can put the 2 module files into different dirs like: +/// +/// project_root/.cache/clangd/module_files/b.cpp/a.pcm +/// project_root/.cache/clangd/module_files/c.cpp/a.pcm +llvm::SmallString<256> getModuleFilesPath(PathRef MainFile, + const GlobalCompilationDatabase &CDB, + StringRef RequiredPrefixDir) { + std::optional PI = CDB.getProjectInfo(MainFile); + if (!PI) +return {}; + + // FIXME: PI->SourceRoot may be empty, depending on the CDB strategy. + llvm::SmallString<256> Result(PI->SourceRoot); + + llvm::sys::path::append(Result, ".cache"); + llvm::sys::path::append(Result, "clangd"); + llvm::sys::path::append(Result, "module_files"); + + llvm::sys::path::append(Result, RequiredPrefixDir); + + llvm::sys::fs::create_directories(Result, /*IgnoreExisting=*/true); + + return Result; +} + +/// Get the absolute path for the filename from the compile command. +llvm::SmallString<128> getAbsolutePath(const tooling::CompileCommand &Cmd) { + llvm::SmallString<128> AbsolutePath; + if (llvm::sys::path::is_absolute(Cmd.Filename)) { +AbsolutePath = Cmd.Filename; + } else { +AbsolutePath = Cmd.Directory; +llvm::sys::path::append(AbsolutePath, Cmd.Filename); +llvm::sys::path::remove_dots(AbsolutePath, true); + } + return AbsolutePath; +} + +/// Get a unique module file path under \param ModuleFilesPrefix. +std::string getUniqueModuleFilePath(StringRef ModuleName, +PathRef ModuleFilesPrefix) { + llvm::SmallString<256> ModuleFilePattern(ModuleFilesPrefix); + auto [PrimaryModuleName, PartitionName] = ModuleName.split(':'); + llvm::sys::path::append(ModuleFilePattern, PrimaryModuleName); + if (!PartitionName.empty()) { +ModuleFilePattern.append("-"); +ModuleFilePattern.append(PartitionName); + } + + ModuleFilePattern.append("-%%-%%-%%-%%-%%-%%"); + ModuleFilePattern.append(".pcm"); + + llvm::SmallString<256> ModuleFilePath; + llvm::sys::fs::createUniquePath(ModuleFilePattern, ModuleFilePath, + /*MakeAbsolute=*/false); + + return (std::string)ModuleFilePath; +} +} // namespace + +bool ModulesBuilder::buildModuleFile(StringRef ModuleName, + const ThreadsafeFS *TFS, + std::shared_ptr MDB, + PathRef ModuleFilesPrefix, + PrerequisiteModules &BuiltModuleFiles) { + if (BuiltModuleFiles.isModuleUnitBuilt(ModuleName)) +return true; + + PathRef ModuleUnitFileName = MDB->getSourceForModuleName(ModuleName); + /// It is possible that we're meeting third party modules (modules whose + /// source are not in the project. e.g, the std module may be a third-party + /// module for most project) or something wrong with the implementation of + /// ProjectModules. + /// FIXME: How should we treat third party modules here? If we want to ignore + /// third party modules, we should return true instead of false here. + /// Currently we simply bail out. + if (ModuleUnitFileName.empty()) +return false; + + for (auto &RequiredModuleName : MDB->getRequiredModules(ModuleUnitFileName)) { +// Return early if there are errors building the module file. +if (!buildModuleFile(RequiredModuleName, TFS, MDB, ModuleFilesPrefix, + BuiltModuleFiles)) { + log("Failed to build module {0}", RequiredModuleName); + return false; +} + } + + auto Cmd = CDB.getCompileCommand(ModuleUnitFileName); + if (!Cmd) +return false; + + std::string ModuleFileName = + getUniqueModuleFilePath(ModuleName, M
[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)
@@ -149,9 +154,13 @@ struct PreambleBuildStats { /// If \p PreambleCallback is set, it will be run on top of the AST while /// building the preamble. /// If Stats is not non-null, build statistics will be exported there. +/// If \p RequiredModuleBuilder is not null, it will scan the source file +/// to see if it is related to modules, and if yes, modules related things +/// will be built. std::shared_ptr buildPreamble(PathRef FileName, CompilerInvocation CI, const ParseInputs &Inputs, bool StoreInMemory, + ModulesBuilder *RequiredModuleBuilder, ChuanqiXu9 wrote: Done https://github.com/llvm/llvm-project/pull/66462 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)
ChuanqiXu9 wrote: Done https://github.com/llvm/llvm-project/pull/66462 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)
@@ -192,8 +192,10 @@ TEST(PreamblePatchTest, PatchesPreambleIncludes) { TU.AdditionalFiles["b.h"] = ""; TU.AdditionalFiles["c.h"] = ""; auto PI = TU.inputs(FS); - auto BaselinePreamble = buildPreamble( - TU.Filename, *buildCompilerInvocation(PI, Diags), PI, true, nullptr); + MockCompilationDatabase CDB; + auto BaselinePreamble = + buildPreamble(TU.Filename, *buildCompilerInvocation(PI, Diags), PI, true, +/*RequiredModuleBuilder=*/nullptr, nullptr); ChuanqiXu9 wrote: Agreed. Done by adding an end-to-end test in the end of `PrerequisiteModulesTest.cpp`. https://github.com/llvm/llvm-project/pull/66462 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)
@@ -44,6 +44,8 @@ struct ParseOptions { bool ImportInsertions = false; }; +class ModulesBuilder; ChuanqiXu9 wrote: Done https://github.com/llvm/llvm-project/pull/66462 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)
@@ -208,15 +208,16 @@ ClangdServer::Options::operator TUScheduler::Options() const { Opts.UpdateDebounce = UpdateDebounce; Opts.ContextProvider = ContextProvider; Opts.PreambleThrottler = PreambleThrottler; + Opts.ExperimentalModulesSupport = ExperimentalModulesSupport; ChuanqiXu9 wrote: Done https://github.com/llvm/llvm-project/pull/66462 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)
@@ -0,0 +1,115 @@ +//===- ModulesBuilder.h --*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// Experimental support for C++20 Modules. +// +// Currently we simplify the implementations by preventing reusing module files +// across different versions and different source files. But this is clearly a +// waste of time and space in the end of the day. +// +// TODO: Supporting reusing module files across different versions and +// different source files. +// +//===--===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_MODULES_BUILDER_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_MODULES_BUILDER_H + +#include "GlobalCompilationDatabase.h" +#include "ProjectModules.h" + +#include "support/Path.h" +#include "support/ThreadsafeFS.h" + +#include "clang/Frontend/CompilerInvocation.h" + +#include "llvm/ADT/SmallString.h" + +#include + +namespace clang { +namespace clangd { + +/// Store all the needed module files information to parse a single +/// source file. e.g., +/// +/// ``` +/// // a.cppm +/// export module a; +/// +/// // b.cppm +/// export module b; +/// import a; +/// +/// // c.cppm +/// export module c; +/// import a; +/// ``` +/// +/// For the source file `c.cppm`, an instance of the class will store +/// the module files for `a.cppm` and `b.cppm`. But the module file for `c.cppm` +/// won't be stored. Since it is not needed to parse `c.cppm`. +/// +/// Users should only get PrerequisiteModules from +/// `ModulesBuilder::buildPrerequisiteModulesFor(...)`. +/// +/// Users can detect whether the PrerequisiteModules is still up to date by +/// calling the `canReuse()` member function. +/// +/// The users should call `adjustHeaderSearchOptions(...)` to update the +/// compilation commands to select the built module files first. Before calling +/// `adjustHeaderSearchOptions()`, users should call `canReuse()` first to check +/// if all the stored module files are valid. In case they are not valid, +/// users should call `ModulesBuilder::buildPrerequisiteModulesFor(...)` again +/// to get the new PrerequisiteModules. +class PrerequisiteModules { +public: + /// Change commands to load the module files recorded in this + /// PrerequisiteModules first. + virtual void + adjustHeaderSearchOptions(HeaderSearchOptions &Options) const = 0; + + /// Whether or not the built module files are up to date. + /// Note that this can only be used after building the module files. + virtual bool + canReuse(const CompilerInvocation &CI, + llvm::IntrusiveRefCntPtr) const = 0; + + /// Return true if the modile file specified by ModuleName is built. + /// Note that this interface will only check the existence of the module + /// file instead of checking the validness of the module file. + virtual bool isModuleUnitBuilt(llvm::StringRef ModuleName) const = 0; + + virtual ~PrerequisiteModules() = default; +}; + +/// This class handles building module files for a given source file. +/// +/// In the future, we want the class to manage the module files acorss +/// different versions and different source files. +class ModulesBuilder { +public: + ModulesBuilder(const GlobalCompilationDatabase &CDB) : CDB(CDB) {} + + ModulesBuilder(const ModulesBuilder &) = delete; + ModulesBuilder(ModulesBuilder &&) = delete; + + ModulesBuilder &operator=(const ModulesBuilder &) = delete; + ModulesBuilder &operator=(ModulesBuilder &&) = delete; + + std::unique_ptr + buildPrerequisiteModulesFor(PathRef File, const ThreadsafeFS *TFS) const; ChuanqiXu9 wrote: Done https://github.com/llvm/llvm-project/pull/66462 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)
@@ -0,0 +1,370 @@ +//===- ModulesBuilder.cpp *- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "ModulesBuilder.h" + +#include "Compiler.h" +#include "support/Logger.h" + +#include "clang/Frontend/FrontendAction.h" +#include "clang/Frontend/FrontendActions.h" + +#include "clang/Serialization/ASTReader.h" + +namespace clang { +namespace clangd { + +namespace { + +// Create a path to store module files. Generally it should be: +// +// {TEMP_DIRS}/clangd/module_files/{PrefixDir}-%%-%%-%%-%%-%%-%%/. +// +// {TEMP_DIRS} is the temporary directory for the system, e.g., "/var/tmp" +// or "C:/TEMP". +// +// '%%' means random value to make the generated path unique. +// +// \param MainFile is used to get the root of the project from global +// compilation database. \param PrefixDir is used to get the user +// defined prefix for module files. This is useful when we want to seperate +// module files. e.g., we want to build module files for the same module unit +// `a.cppm` with 2 different users `b.cpp` and `c.cpp` and we don't want the +// module file for `b.cpp` be conflict with the module files for `c.cpp`. Then +// we can put the 2 module files into different dirs like: +// +// ${TEMP_DIRS}/clangd/module_files/b.cpp/a.pcm +// ${TEMP_DIRS}/clangd/module_files/c.cpp/a.pcm +// +// TODO: Move these module fils out of the temporary directory if the module +// files are persistent. +llvm::SmallString<256> getUniqueModuleFilesPath(PathRef MainFile, +llvm::StringRef PrefixDir) { + llvm::SmallString<256> ResultPattern; + + llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/true, + ResultPattern); + + llvm::sys::path::append(ResultPattern, "clangd"); + llvm::sys::path::append(ResultPattern, "module_files"); + + llvm::sys::path::append(ResultPattern, PrefixDir); + + ResultPattern.append("-%%-%%-%%-%%-%%-%%"); + + llvm::SmallString<256> Result; + llvm::sys::fs::createUniquePath(ResultPattern, Result, + /*MakeAbsolute=*/false); + + llvm::sys::fs::create_directories(Result); + return Result; +} + +// Get the absolute path for the filename from the compile command. +llvm::SmallString<128> getAbsolutePath(const tooling::CompileCommand &Cmd) { + llvm::SmallString<128> AbsolutePath; + if (llvm::sys::path::is_absolute(Cmd.Filename)) { +AbsolutePath = Cmd.Filename; + } else { +AbsolutePath = Cmd.Directory; +llvm::sys::path::append(AbsolutePath, Cmd.Filename); +llvm::sys::path::remove_dots(AbsolutePath, true); + } + return AbsolutePath; +} + +// Get a unique module file path under \param ModuleFilesPrefix. +std::string getModuleFilePath(llvm::StringRef ModuleName, + PathRef ModuleFilesPrefix) { + llvm::SmallString<256> ModuleFilePattern(ModuleFilesPrefix); + auto [PrimaryModuleName, PartitionName] = ModuleName.split(':'); + llvm::sys::path::append(ModuleFilePattern, PrimaryModuleName); + if (!PartitionName.empty()) { +ModuleFilePattern.append("-"); +ModuleFilePattern.append(PartitionName); + } + + ModuleFilePattern.append(".pcm"); + + llvm::SmallString<256> ModuleFilePath; + llvm::sys::fs::createUniquePath(ModuleFilePattern, ModuleFilePath, + /*MakeAbsolute=*/false); + + return std::string(ModuleFilePath); +} +} // namespace + +// FailedPrerequisiteModules - stands for the PrerequisiteModules which has +// errors happened during the building process. +class FailedPrerequisiteModules : public PrerequisiteModules { +public: + ~FailedPrerequisiteModules() override = default; + + // We shouldn't adjust the compilation commands based on + // FailedPrerequisiteModules. + void adjustHeaderSearchOptions(HeaderSearchOptions &Options) const override { + } + + // FailedPrerequisiteModules can never be reused. + bool + canReuse(const CompilerInvocation &CI, + llvm::IntrusiveRefCntPtr) const override { +return false; + } + + // No module unit got built in FailedPrerequisiteModules. + bool isModuleUnitBuilt(llvm::StringRef ModuleName) const override { +return false; + } +}; + +// StandalonePrerequisiteModules - stands for PrerequisiteModules for which all +// the required modules are built successfully. All the module files +// are owned by the StandalonePrerequisiteModules class. +// +// Any of the built module files won't be shared with other instances of the +// class. So that we can avoid worrying thread safety. +// +// We don't need to worry about duplicated module names here since the standard +// guarantees the module names should be unique to a pr
[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)
@@ -0,0 +1,370 @@ +//===- ModulesBuilder.cpp *- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "ModulesBuilder.h" + +#include "Compiler.h" +#include "support/Logger.h" + +#include "clang/Frontend/FrontendAction.h" +#include "clang/Frontend/FrontendActions.h" + +#include "clang/Serialization/ASTReader.h" + +namespace clang { +namespace clangd { + +namespace { + +// Create a path to store module files. Generally it should be: +// +// {TEMP_DIRS}/clangd/module_files/{PrefixDir}-%%-%%-%%-%%-%%-%%/. +// +// {TEMP_DIRS} is the temporary directory for the system, e.g., "/var/tmp" +// or "C:/TEMP". +// +// '%%' means random value to make the generated path unique. +// +// \param MainFile is used to get the root of the project from global +// compilation database. \param PrefixDir is used to get the user +// defined prefix for module files. This is useful when we want to seperate +// module files. e.g., we want to build module files for the same module unit +// `a.cppm` with 2 different users `b.cpp` and `c.cpp` and we don't want the +// module file for `b.cpp` be conflict with the module files for `c.cpp`. Then +// we can put the 2 module files into different dirs like: +// +// ${TEMP_DIRS}/clangd/module_files/b.cpp/a.pcm +// ${TEMP_DIRS}/clangd/module_files/c.cpp/a.pcm +// +// TODO: Move these module fils out of the temporary directory if the module +// files are persistent. +llvm::SmallString<256> getUniqueModuleFilesPath(PathRef MainFile, +llvm::StringRef PrefixDir) { + llvm::SmallString<256> ResultPattern; + + llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/true, + ResultPattern); + + llvm::sys::path::append(ResultPattern, "clangd"); + llvm::sys::path::append(ResultPattern, "module_files"); + + llvm::sys::path::append(ResultPattern, PrefixDir); + + ResultPattern.append("-%%-%%-%%-%%-%%-%%"); + + llvm::SmallString<256> Result; + llvm::sys::fs::createUniquePath(ResultPattern, Result, + /*MakeAbsolute=*/false); + + llvm::sys::fs::create_directories(Result); + return Result; +} + +// Get the absolute path for the filename from the compile command. +llvm::SmallString<128> getAbsolutePath(const tooling::CompileCommand &Cmd) { + llvm::SmallString<128> AbsolutePath; + if (llvm::sys::path::is_absolute(Cmd.Filename)) { +AbsolutePath = Cmd.Filename; + } else { +AbsolutePath = Cmd.Directory; +llvm::sys::path::append(AbsolutePath, Cmd.Filename); +llvm::sys::path::remove_dots(AbsolutePath, true); + } + return AbsolutePath; +} + +// Get a unique module file path under \param ModuleFilesPrefix. +std::string getModuleFilePath(llvm::StringRef ModuleName, + PathRef ModuleFilesPrefix) { + llvm::SmallString<256> ModuleFilePattern(ModuleFilesPrefix); + auto [PrimaryModuleName, PartitionName] = ModuleName.split(':'); + llvm::sys::path::append(ModuleFilePattern, PrimaryModuleName); + if (!PartitionName.empty()) { +ModuleFilePattern.append("-"); +ModuleFilePattern.append(PartitionName); + } + + ModuleFilePattern.append(".pcm"); + + llvm::SmallString<256> ModuleFilePath; + llvm::sys::fs::createUniquePath(ModuleFilePattern, ModuleFilePath, + /*MakeAbsolute=*/false); + + return std::string(ModuleFilePath); +} +} // namespace + +// FailedPrerequisiteModules - stands for the PrerequisiteModules which has +// errors happened during the building process. +class FailedPrerequisiteModules : public PrerequisiteModules { +public: + ~FailedPrerequisiteModules() override = default; + + // We shouldn't adjust the compilation commands based on + // FailedPrerequisiteModules. + void adjustHeaderSearchOptions(HeaderSearchOptions &Options) const override { + } + + // FailedPrerequisiteModules can never be reused. + bool + canReuse(const CompilerInvocation &CI, + llvm::IntrusiveRefCntPtr) const override { +return false; + } + + // No module unit got built in FailedPrerequisiteModules. + bool isModuleUnitBuilt(llvm::StringRef ModuleName) const override { +return false; + } +}; + +// StandalonePrerequisiteModules - stands for PrerequisiteModules for which all +// the required modules are built successfully. All the module files +// are owned by the StandalonePrerequisiteModules class. +// +// Any of the built module files won't be shared with other instances of the +// class. So that we can avoid worrying thread safety. +// +// We don't need to worry about duplicated module names here since the standard +// guarantees the module names should be unique to a pr
[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)
@@ -0,0 +1,115 @@ +//===- ModulesBuilder.h --*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// Experimental support for C++20 Modules. +// +// Currently we simplify the implementations by preventing reusing module files +// across different versions and different source files. But this is clearly a +// waste of time and space in the end of the day. +// +// TODO: Supporting reusing module files across different versions and +// different source files. +// +//===--===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_MODULES_BUILDER_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_MODULES_BUILDER_H + +#include "GlobalCompilationDatabase.h" +#include "ProjectModules.h" + +#include "support/Path.h" +#include "support/ThreadsafeFS.h" + +#include "clang/Frontend/CompilerInvocation.h" + +#include "llvm/ADT/SmallString.h" + +#include + +namespace clang { +namespace clangd { + +/// Store all the needed module files information to parse a single +/// source file. e.g., +/// +/// ``` +/// // a.cppm +/// export module a; +/// +/// // b.cppm +/// export module b; +/// import a; +/// +/// // c.cppm +/// export module c; +/// import a; +/// ``` +/// +/// For the source file `c.cppm`, an instance of the class will store +/// the module files for `a.cppm` and `b.cppm`. But the module file for `c.cppm` +/// won't be stored. Since it is not needed to parse `c.cppm`. +/// +/// Users should only get PrerequisiteModules from +/// `ModulesBuilder::buildPrerequisiteModulesFor(...)`. +/// +/// Users can detect whether the PrerequisiteModules is still up to date by +/// calling the `canReuse()` member function. +/// +/// The users should call `adjustHeaderSearchOptions(...)` to update the +/// compilation commands to select the built module files first. Before calling +/// `adjustHeaderSearchOptions()`, users should call `canReuse()` first to check +/// if all the stored module files are valid. In case they are not valid, +/// users should call `ModulesBuilder::buildPrerequisiteModulesFor(...)` again +/// to get the new PrerequisiteModules. +class PrerequisiteModules { +public: + /// Change commands to load the module files recorded in this + /// PrerequisiteModules first. + virtual void + adjustHeaderSearchOptions(HeaderSearchOptions &Options) const = 0; + + /// Whether or not the built module files are up to date. + /// Note that this can only be used after building the module files. + virtual bool + canReuse(const CompilerInvocation &CI, + llvm::IntrusiveRefCntPtr) const = 0; + + /// Return true if the modile file specified by ModuleName is built. + /// Note that this interface will only check the existence of the module + /// file instead of checking the validness of the module file. + virtual bool isModuleUnitBuilt(llvm::StringRef ModuleName) const = 0; ChuanqiXu9 wrote: Done https://github.com/llvm/llvm-project/pull/66462 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)
@@ -0,0 +1,370 @@ +//===- ModulesBuilder.cpp *- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "ModulesBuilder.h" + +#include "Compiler.h" +#include "support/Logger.h" + +#include "clang/Frontend/FrontendAction.h" +#include "clang/Frontend/FrontendActions.h" + +#include "clang/Serialization/ASTReader.h" + +namespace clang { +namespace clangd { + +namespace { + +// Create a path to store module files. Generally it should be: +// +// {TEMP_DIRS}/clangd/module_files/{PrefixDir}-%%-%%-%%-%%-%%-%%/. +// +// {TEMP_DIRS} is the temporary directory for the system, e.g., "/var/tmp" +// or "C:/TEMP". +// +// '%%' means random value to make the generated path unique. +// +// \param MainFile is used to get the root of the project from global +// compilation database. \param PrefixDir is used to get the user +// defined prefix for module files. This is useful when we want to seperate +// module files. e.g., we want to build module files for the same module unit +// `a.cppm` with 2 different users `b.cpp` and `c.cpp` and we don't want the +// module file for `b.cpp` be conflict with the module files for `c.cpp`. Then +// we can put the 2 module files into different dirs like: +// +// ${TEMP_DIRS}/clangd/module_files/b.cpp/a.pcm +// ${TEMP_DIRS}/clangd/module_files/c.cpp/a.pcm +// +// TODO: Move these module fils out of the temporary directory if the module +// files are persistent. +llvm::SmallString<256> getUniqueModuleFilesPath(PathRef MainFile, +llvm::StringRef PrefixDir) { + llvm::SmallString<256> ResultPattern; + + llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/true, + ResultPattern); + + llvm::sys::path::append(ResultPattern, "clangd"); + llvm::sys::path::append(ResultPattern, "module_files"); + + llvm::sys::path::append(ResultPattern, PrefixDir); + + ResultPattern.append("-%%-%%-%%-%%-%%-%%"); + + llvm::SmallString<256> Result; + llvm::sys::fs::createUniquePath(ResultPattern, Result, + /*MakeAbsolute=*/false); + + llvm::sys::fs::create_directories(Result); + return Result; +} + +// Get the absolute path for the filename from the compile command. +llvm::SmallString<128> getAbsolutePath(const tooling::CompileCommand &Cmd) { + llvm::SmallString<128> AbsolutePath; + if (llvm::sys::path::is_absolute(Cmd.Filename)) { +AbsolutePath = Cmd.Filename; + } else { +AbsolutePath = Cmd.Directory; +llvm::sys::path::append(AbsolutePath, Cmd.Filename); +llvm::sys::path::remove_dots(AbsolutePath, true); + } + return AbsolutePath; +} + +// Get a unique module file path under \param ModuleFilesPrefix. +std::string getModuleFilePath(llvm::StringRef ModuleName, + PathRef ModuleFilesPrefix) { + llvm::SmallString<256> ModuleFilePattern(ModuleFilesPrefix); + auto [PrimaryModuleName, PartitionName] = ModuleName.split(':'); + llvm::sys::path::append(ModuleFilePattern, PrimaryModuleName); + if (!PartitionName.empty()) { +ModuleFilePattern.append("-"); +ModuleFilePattern.append(PartitionName); + } + + ModuleFilePattern.append(".pcm"); + + llvm::SmallString<256> ModuleFilePath; + llvm::sys::fs::createUniquePath(ModuleFilePattern, ModuleFilePath, + /*MakeAbsolute=*/false); + + return std::string(ModuleFilePath); +} +} // namespace + +// FailedPrerequisiteModules - stands for the PrerequisiteModules which has +// errors happened during the building process. +class FailedPrerequisiteModules : public PrerequisiteModules { +public: + ~FailedPrerequisiteModules() override = default; + + // We shouldn't adjust the compilation commands based on + // FailedPrerequisiteModules. + void adjustHeaderSearchOptions(HeaderSearchOptions &Options) const override { + } + + // FailedPrerequisiteModules can never be reused. + bool + canReuse(const CompilerInvocation &CI, + llvm::IntrusiveRefCntPtr) const override { +return false; + } + + // No module unit got built in FailedPrerequisiteModules. + bool isModuleUnitBuilt(llvm::StringRef ModuleName) const override { +return false; + } +}; + +// StandalonePrerequisiteModules - stands for PrerequisiteModules for which all +// the required modules are built successfully. All the module files +// are owned by the StandalonePrerequisiteModules class. +// +// Any of the built module files won't be shared with other instances of the +// class. So that we can avoid worrying thread safety. +// +// We don't need to worry about duplicated module names here since the standard +// guarantees the module names should be unique to a pr
[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)
ChuanqiXu9 wrote: Done https://github.com/llvm/llvm-project/pull/66462 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)
@@ -0,0 +1,87 @@ +//===- PrerequisiteModules.h -*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_PREREQUISITEMODULES_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_PREREQUISITEMODULES_H + +#include "Compiler.h" +#include "support/Path.h" + +#include "clang/Lex/HeaderSearchOptions.h" + +#include "llvm/ADT/StringSet.h" + +namespace clang { +namespace clangd { + +class ModulesBuilder; + +/// Store all the needed module files information to parse a single +/// source file. e.g., +/// +/// ``` +/// // a.cppm +/// export module a; +/// +/// // b.cppm +/// export module b; +/// import a; +/// +/// // c.cppm +/// export module c; +/// import a; +/// ``` +/// +/// For the source file `c.cppm`, an instance of the class will store +/// the module files for `a.cppm` and `b.cppm`. But the module file for `c.cppm` ChuanqiXu9 wrote: Oh, nice catch. The things written is not consistent with what I thought. I've refactored it. Thanks. https://github.com/llvm/llvm-project/pull/66462 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] `doesNotMutateObject`: Handle calls to member functions … (PR #94362)
https://github.com/legrosbuffle updated https://github.com/llvm/llvm-project/pull/94362 >From 8a7e3ee49295b55193440da6b796c9ada43ee5ef Mon Sep 17 00:00:00 2001 From: Clement Courbet Date: Tue, 4 Jun 2024 12:49:39 + Subject: [PATCH 1/2] [clang-tidy] `doesNotMutateObject`: Handle calls to member functions and operators that have non-const overloads. This allows `unnecessary-copy-initialization` to warn on more cases. The common case is a class with a a set of const/non-sconst overloads (e.g. std::vector::operator[]). ``` void F() { std::vector v; // ... const Expensive e = v[i]; } ``` --- .../UnnecessaryCopyInitialization.cpp | 21 ++- .../clang-tidy/utils/DeclRefExprUtils.cpp | 163 +- clang-tools-extra/docs/ReleaseNotes.rst | 4 +- .../unnecessary-copy-initialization.cpp | 29 +++- .../clang-tidy/DeclRefExprUtilsTest.cpp | 39 - 5 files changed, 229 insertions(+), 27 deletions(-) diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp index 9beb185cba929..78a1f9a73687d 100644 --- a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp +++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp @@ -75,16 +75,15 @@ void recordRemoval(const DeclStmt &Stmt, ASTContext &Context, } } -AST_MATCHER_FUNCTION_P(StatementMatcher, isConstRefReturningMethodCall, +AST_MATCHER_FUNCTION_P(StatementMatcher, isRefReturningMethodCall, std::vector, ExcludedContainerTypes) { // Match method call expressions where the `this` argument is only used as - // const, this will be checked in `check()` part. This returned const - // reference is highly likely to outlive the local const reference of the - // variable being declared. The assumption is that the const reference being - // returned either points to a global static variable or to a member of the - // called object. + // const, this will be checked in `check()` part. This returned reference is + // highly likely to outlive the local const reference of the variable being + // declared. The assumption is that the reference being returned either points + // to a global static variable or to a member of the called object. const auto MethodDecl = - cxxMethodDecl(returns(hasCanonicalType(matchers::isReferenceToConst( + cxxMethodDecl(returns(hasCanonicalType(referenceType( .bind(MethodDeclId); const auto ReceiverExpr = ignoringParenImpCasts(declRefExpr(to(varDecl().bind(ObjectArgId; @@ -121,7 +120,7 @@ AST_MATCHER_FUNCTION_P(StatementMatcher, initializerReturnsReferenceToConst, declRefExpr(to(varDecl(hasLocalStorage()).bind(OldVarDeclId))); return expr( anyOf(isConstRefReturningFunctionCall(), -isConstRefReturningMethodCall(ExcludedContainerTypes), +isRefReturningMethodCall(ExcludedContainerTypes), ignoringImpCasts(OldVarDeclRef), ignoringImpCasts(unaryOperator(hasOperatorName("&"), hasUnaryOperand(OldVarDeclRef); @@ -259,9 +258,9 @@ void UnnecessaryCopyInitialization::registerMatchers(MatchFinder *Finder) { .bind("blockStmt"); }; - Finder->addMatcher(LocalVarCopiedFrom(anyOf(isConstRefReturningFunctionCall(), - isConstRefReturningMethodCall( - ExcludedContainerTypes))), + Finder->addMatcher(LocalVarCopiedFrom(anyOf( + isConstRefReturningFunctionCall(), + isRefReturningMethodCall(ExcludedContainerTypes))), this); Finder->addMatcher(LocalVarCopiedFrom(declRefExpr( diff --git a/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp b/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp index a48e45e135681..4ee8a3628061b 100644 --- a/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp +++ b/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp @@ -36,6 +36,111 @@ void extractNodesByIdTo(ArrayRef Matches, StringRef ID, Nodes.insert(Match.getNodeAs(ID)); } +// If `D` has a const-qualified overload with otherwise identical +// ref-qualifiers, returns that overload. +const CXXMethodDecl *findConstOverload(const CXXMethodDecl &D) { + assert(!D.isConst()); + + DeclContext::lookup_result lookup_result = + D.getParent()->lookup(D.getNameInfo().getName()); + if (lookup_result.isSingleResult()) { +// No overload. +return nullptr; + } + for (const Decl *overload : lookup_result) { +const CXXMethodDecl *candidate = dyn_cast(overload); +if (candidate && !candidate->isDeleted() && candidate->isConst() && +candidate->getRefQualifier() == D.getRefQualifier()) { + return candidate; +} + } + return nullptr; +} + +// Returns true
[clang] [llvm] [ARM] r11 is reserved when using -mframe-chain=aapcs (PR #86951)
github-actions[bot] wrote: :warning: C/C++ code formatter, clang-format found issues in your code. :warning: You can test this locally with the following command: ``bash git-clang-format --diff eea05c6b3369736b703e2a5e3ca08ba6ad8a51dc 7272dd8f58e9f445f758a10ae3d91aaa166c91f1 -- clang/include/clang/Basic/CodeGenOptions.h clang/lib/CodeGen/CGCall.cpp clang/lib/CodeGen/CodeGenModule.cpp clang/lib/Driver/ToolChains/Arch/ARM.cpp clang/lib/Driver/ToolChains/Clang.cpp clang/lib/Driver/ToolChains/CommonArgs.cpp llvm/include/llvm/Support/CodeGen.h llvm/include/llvm/Target/TargetOptions.h llvm/lib/CodeGen/CommandFlags.cpp llvm/lib/CodeGen/TargetOptionsImpl.cpp llvm/lib/IR/Function.cpp llvm/lib/IR/Verifier.cpp llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp llvm/lib/Target/ARM/ARMFrameLowering.cpp llvm/lib/Target/ARM/ARMFrameLowering.h `` View the diff from clang-format here. ``diff diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index 6887926cb3..00523a84d3 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -127,10 +127,10 @@ public: std::string BinutilsVersion; enum class FramePointerKind { -None,// Omit all frame pointers. -Reserved,// Maintain valid frame pointer chain. -NonLeaf, // Keep non-leaf frame pointers. -All, // Keep all frame pointers. +None, // Omit all frame pointers. +Reserved, // Maintain valid frame pointer chain. +NonLeaf, // Keep non-leaf frame pointers. +All, // Keep all frame pointers. }; static StringRef getFramePointerKindName(FramePointerKind Kind) { diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 61c8f6812c..2a4c1369f5 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -166,7 +166,7 @@ static bool useFramePointerForTargetByDefault(const llvm::opt::ArgList &Args, static bool useLeafFramePointerForTargetByDefault(const llvm::Triple &Triple) { if (Triple.isAArch64() || Triple.isPS() || Triple.isVE() || -(Triple.isAndroid() && Triple.isRISCV64())) + (Triple.isAndroid() && Triple.isRISCV64())) return false; return true; `` https://github.com/llvm/llvm-project/pull/86951 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc] [llvm] [AMDGPU] Implement variadic functions by IR lowering (PR #93362)
@@ -992,6 +993,8 @@ void AMDGPUPassConfig::addIRPasses() { if (isPassEnabled(EnableImageIntrinsicOptimizer)) addPass(createAMDGPUImageIntrinsicOptimizerPass(&TM)); + addPass(createExpandVariadicsPass(ExpandVariadicsMode::Lowering)); JonChesterfield wrote: I'm also paranoid enough to want that, it's '--expand-variadics-override=disable' from the command line or changing the ::Lowering in that line to ::Disable. Commenting out the addPass also kills it, but would cause the lit pipeline tests to fail. I'll put a comment above that pass saying this. https://github.com/llvm/llvm-project/pull/93362 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [serialization] no transitive decl change (PR #92083)
DavidSpickett wrote: > Thanks. Reproduced. But it surprised me that I can't run the commands you > mentioned, but I need to run: > ./bin/lldb-dotest -p TestTemplateWithSameArg.py -G gmodules Running the tests as modules is perhaps opt in, we have the ability to run them with different debug info types too. So this is not surprising. Well, it is for you, but doesn't mean there's anything wrong here :) > And I am also slightly surprised that after I change the code, it doesn't > work if I run ninja lldb-test only I need to run ninja clang lldb. Do I > misconfigure anything? I build lldb by: My comment about `lld-test` referred to a different failing test I think (and if we did have some dependencies incorrect, it wouldn't surprise me). Nothing wrong with that config line though. So good news is Linux and Windows lldb are ok (Mac will report back soon I assume), but now we have failures on 32 bit Arm builds: https://lab.llvm.org/buildbot/#/builders/245/builds/25498 I'm going to reproduce this shortly but my bet is that this is undefined behaviour of some kind. It may not be due to your code but your code may be exposing a pre-existing issue. https://github.com/llvm/llvm-project/pull/92083 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [ARM] r11 is reserved when using -mframe-chain=aapcs (PR #86951)
https://github.com/ostannard updated https://github.com/llvm/llvm-project/pull/86951 >From 1e141e80b0abf45f160c06f8eb39623df16434d8 Mon Sep 17 00:00:00 2001 From: Oliver Stannard Date: Thu, 6 Jun 2024 09:34:13 +0100 Subject: [PATCH 1/4] [IR] Add target-independent option to preserve frame-pointer register This adds a new value "reserved" to the "frame-pointer" function attribute. When this value is used, the frame pointer register must either be reserved, or updated to point to a new frame record, but must not be used for any other purpose. This is not yet supported by most targets, but will be used for the Arm -mframe-chain= option. --- clang/include/clang/Basic/CodeGenOptions.def | 2 +- clang/include/clang/Basic/CodeGenOptions.h | 3 +++ clang/include/clang/Driver/Options.td| 4 ++-- clang/lib/CodeGen/CGCall.cpp | 1 + clang/lib/CodeGen/CodeGenModule.cpp | 3 +++ clang/lib/Driver/ToolChains/Clang.cpp| 3 +++ llvm/docs/LangRef.rst| 6 +- llvm/include/llvm/Support/CodeGen.h | 2 +- llvm/include/llvm/Target/TargetOptions.h | 5 + llvm/lib/CodeGen/CommandFlags.cpp| 5 + llvm/lib/CodeGen/TargetOptionsImpl.cpp | 21 ++-- llvm/lib/IR/Function.cpp | 3 +++ llvm/lib/IR/Verifier.cpp | 2 +- 13 files changed, 52 insertions(+), 8 deletions(-) diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 07b0ca1691a67..7ffc40a00504f 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -61,7 +61,7 @@ CODEGENOPT(SeparateNamedSections, 1, 0) ///< Set for -fseparate-named-sections. CODEGENOPT(EnableAIXExtendedAltivecABI, 1, 0) ///< Set for -mabi=vec-extabi. Enables the extended Altivec ABI on AIX. CODEGENOPT(XCOFFReadOnlyPointers, 1, 0) ///< Set for -mxcoff-roptr. CODEGENOPT(AllTocData, 1, 0) ///< AIX -mtocdata -ENUM_CODEGENOPT(FramePointer, FramePointerKind, 2, FramePointerKind::None) /// frame-pointer: all,non-leaf,none +ENUM_CODEGENOPT(FramePointer, FramePointerKind, 2, FramePointerKind::None) /// frame-pointer: all,non-leaf,reserved,none CODEGENOPT(ClearASTBeforeBackend , 1, 0) ///< Free the AST before running backend code generation. Only works with -disable-free. CODEGENOPT(DisableFree , 1, 0) ///< Don't free memory. diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index 9469a424045bb..6887926cb34da 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -128,6 +128,7 @@ class CodeGenOptions : public CodeGenOptionsBase { enum class FramePointerKind { None,// Omit all frame pointers. +Reserved,// Maintain valid frame pointer chain. NonLeaf, // Keep non-leaf frame pointers. All, // Keep all frame pointers. }; @@ -136,6 +137,8 @@ class CodeGenOptions : public CodeGenOptionsBase { switch (Kind) { case FramePointerKind::None: return "none"; +case FramePointerKind::Reserved: + return "reserved"; case FramePointerKind::NonLeaf: return "non-leaf"; case FramePointerKind::All: diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 57f37c5023110..9b89b394cef52 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -7706,8 +7706,8 @@ def pic_is_pie : Flag<["-"], "pic-is-pie">, MarshallingInfoFlag>; def mframe_pointer_EQ : Joined<["-"], "mframe-pointer=">, - HelpText<"Specify which frame pointers to retain.">, Values<"all,non-leaf,none">, - NormalizedValuesScope<"CodeGenOptions::FramePointerKind">, NormalizedValues<["All", "NonLeaf", "None"]>, + HelpText<"Specify which frame pointers to retain.">, Values<"all,non-leaf,reserved,none">, + NormalizedValuesScope<"CodeGenOptions::FramePointerKind">, NormalizedValues<["All", "NonLeaf", "Reserved", "None"]>, MarshallingInfoEnum, "None">; diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 97449a5e51e73..65d82285b907b 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1917,6 +1917,7 @@ static void getTrivialDefaultFunctionAttributes( case CodeGenOptions::FramePointerKind::None: // This is the default behavior. break; +case CodeGenOptions::FramePointerKind::Reserved: case CodeGenOptions::FramePointerKind::NonLeaf: case CodeGenOptions::FramePointerKind::All: FuncAttrs.addAttribute("frame-pointer", diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index be7bf0b72dc0c..75b1449090389 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1328,6 +1328,9 @@ void CodeGenModule::Release() { case CodeGenOptions:
[clang] a86c1e7 - [clang][Interp] Member Pointers (#91303)
Author: Timm Baeder Date: 2024-06-06T11:17:48+02:00 New Revision: a86c1e7175d4acd8357326184bf4f88c8192676f URL: https://github.com/llvm/llvm-project/commit/a86c1e7175d4acd8357326184bf4f88c8192676f DIFF: https://github.com/llvm/llvm-project/commit/a86c1e7175d4acd8357326184bf4f88c8192676f.diff LOG: [clang][Interp] Member Pointers (#91303) This adds a `MemberPointer` class along with a `PT_MemberPtr` primitive type. A `MemberPointer` has a `Pointer` Base as well as a `Decl*` (could be `ValueDecl*`?) decl it points to. For the actual logic, this mainly changes the way we handle `PtrMemOp`s in `VisitBinaryOperator`. Added: clang/lib/AST/Interp/MemberPointer.cpp clang/lib/AST/Interp/MemberPointer.h clang/test/AST/Interp/memberpointers.cpp Modified: clang/lib/AST/CMakeLists.txt clang/lib/AST/Interp/ByteCodeExprGen.cpp clang/lib/AST/Interp/Context.cpp clang/lib/AST/Interp/Context.h clang/lib/AST/Interp/Descriptor.cpp clang/lib/AST/Interp/Disasm.cpp clang/lib/AST/Interp/Interp.cpp clang/lib/AST/Interp/Interp.h clang/lib/AST/Interp/InterpFrame.cpp clang/lib/AST/Interp/InterpStack.cpp clang/lib/AST/Interp/InterpStack.h clang/lib/AST/Interp/Opcodes.td clang/lib/AST/Interp/Pointer.cpp clang/lib/AST/Interp/Pointer.h clang/lib/AST/Interp/PrimType.cpp clang/lib/AST/Interp/PrimType.h clang/test/AST/Interp/eval-order.cpp clang/test/AST/Interp/literals.cpp clang/test/CodeGenCXX/pointers-to-data-members.cpp clang/test/SemaCXX/attr-weak.cpp clang/test/SemaCXX/nullptr_in_arithmetic_ops.cpp clang/unittests/AST/Interp/toAPValue.cpp Removed: diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt index 3faefb54f599f..a5d3dacfc1a84 100644 --- a/clang/lib/AST/CMakeLists.txt +++ b/clang/lib/AST/CMakeLists.txt @@ -87,6 +87,7 @@ add_clang_library(clangAST Interp/Record.cpp Interp/Source.cpp Interp/State.cpp + Interp/MemberPointer.cpp Interp/InterpShared.cpp ItaniumCXXABI.cpp ItaniumMangle.cpp diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index ea259639dace7..d124248a3605f 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -100,6 +100,35 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { return this->emitMemcpy(CE); } + case CK_DerivedToBaseMemberPointer: { +assert(classifyPrim(CE->getType()) == PT_MemberPtr); +assert(classifyPrim(SubExpr->getType()) == PT_MemberPtr); +const auto *FromMP = SubExpr->getType()->getAs(); +const auto *ToMP = CE->getType()->getAs(); + +unsigned DerivedOffset = collectBaseOffset(QualType(ToMP->getClass(), 0), + QualType(FromMP->getClass(), 0)); + +if (!this->visit(SubExpr)) + return false; + +return this->emitGetMemberPtrBasePop(DerivedOffset, CE); + } + + case CK_BaseToDerivedMemberPointer: { +assert(classifyPrim(CE) == PT_MemberPtr); +assert(classifyPrim(SubExpr) == PT_MemberPtr); +const auto *FromMP = SubExpr->getType()->getAs(); +const auto *ToMP = CE->getType()->getAs(); + +unsigned DerivedOffset = collectBaseOffset(QualType(FromMP->getClass(), 0), + QualType(ToMP->getClass(), 0)); + +if (!this->visit(SubExpr)) + return false; +return this->emitGetMemberPtrBasePop(-DerivedOffset, CE); + } + case CK_UncheckedDerivedToBase: case CK_DerivedToBase: { if (!this->visit(SubExpr)) @@ -187,7 +216,8 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { return this->emitCastFloatingIntegral(*ToT, CE); } - case CK_NullToPointer: { + case CK_NullToPointer: + case CK_NullToMemberPointer: { if (DiscardResult) return true; @@ -326,7 +356,8 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { return this->emitCast(*FromT, *ToT, CE); } - case CK_PointerToBoolean: { + case CK_PointerToBoolean: + case CK_MemberPointerToBoolean: { PrimType PtrT = classifyPrim(SubExpr->getType()); // Just emit p != nullptr for this. @@ -534,8 +565,23 @@ bool ByteCodeExprGen::VisitBinaryOperator(const BinaryOperator *BO) { BO->isComparisonOp()) return this->emitComplexComparison(LHS, RHS, BO); - if (BO->isPtrMemOp()) -return this->visit(RHS); + if (BO->isPtrMemOp()) { +if (!this->visit(LHS)) + return false; + +if (!this->visit(RHS)) + return false; + +if (!this->emitToMemberPtr(BO)) + return false; + +if (classifyPrim(BO) == PT_MemberPtr) + return true; + +if (!this->emitCastMemberPtrPtr(BO)) + return false; +return DiscardResult ? this->emitPopPtr(BO) : true; + } // Typecheck the args. std::optional LT = classify(LHS->getType()); @@ -2773,6 +2819,8 @@ bool ByteCodeEx
[clang] [clang][Interp] Member Pointers (PR #91303)
https://github.com/tbaederr closed https://github.com/llvm/llvm-project/pull/91303 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)
ChuanqiXu9 wrote: > I think that needs to happen eventually as well Agreed. > similar to preambles supporting in-memory storage, and it's actually not that > hard, GenerateModuleInterfaceAction already has an overrideable > CreateOutputFile method. I am slightly confused. Do you say to move the IO to the memory instead of on-disk files? If true, we're close to that since we can write them to /tmp directories. I thought you're saying we need to get rid of the reading and writing process for module files. > Also this comment is not solely about virtiualizing CDB, but also about the > way we're setting up tests. I don't think we need any of the compile flags > you're explicitly setting in the tests. The whole purpose of current > implementation is to rely on new module paths we provide into the > header-search-options. So there isn't any value in spelling those out > explicitly, rendering test setup more complicated. Agreed. In the new added test, I meant to use `TestTU` with `AdditionalFiles` to mimic a multiple module units project, but it fails. It looks like it can only accept headers. I feel there are a lot of spaces to improve. But I think it may be fine to leave it as is and improve this later. My plan after this patch is to make the module files reusable. I think the functionality to support modules in clangd is at least usable after that. https://github.com/llvm/llvm-project/pull/66462 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] `doesNotMutateObject`: Handle calls to member functions … (PR #94362)
@@ -259,9 +258,9 @@ void UnnecessaryCopyInitialization::registerMatchers(MatchFinder *Finder) { .bind("blockStmt"); }; - Finder->addMatcher(LocalVarCopiedFrom(anyOf(isConstRefReturningFunctionCall(), - isConstRefReturningMethodCall( - ExcludedContainerTypes))), + Finder->addMatcher(LocalVarCopiedFrom(anyOf( + isConstRefReturningFunctionCall(), + isRefReturningMethodCall(ExcludedContainerTypes))), legrosbuffle wrote: Done https://github.com/llvm/llvm-project/pull/94362 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] `doesNotMutateObject`: Handle calls to member functions … (PR #94362)
https://github.com/legrosbuffle updated https://github.com/llvm/llvm-project/pull/94362 >From 8a7e3ee49295b55193440da6b796c9ada43ee5ef Mon Sep 17 00:00:00 2001 From: Clement Courbet Date: Tue, 4 Jun 2024 12:49:39 + Subject: [PATCH 1/3] [clang-tidy] `doesNotMutateObject`: Handle calls to member functions and operators that have non-const overloads. This allows `unnecessary-copy-initialization` to warn on more cases. The common case is a class with a a set of const/non-sconst overloads (e.g. std::vector::operator[]). ``` void F() { std::vector v; // ... const Expensive e = v[i]; } ``` --- .../UnnecessaryCopyInitialization.cpp | 21 ++- .../clang-tidy/utils/DeclRefExprUtils.cpp | 163 +- clang-tools-extra/docs/ReleaseNotes.rst | 4 +- .../unnecessary-copy-initialization.cpp | 29 +++- .../clang-tidy/DeclRefExprUtilsTest.cpp | 39 - 5 files changed, 229 insertions(+), 27 deletions(-) diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp index 9beb185cba929..78a1f9a73687d 100644 --- a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp +++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp @@ -75,16 +75,15 @@ void recordRemoval(const DeclStmt &Stmt, ASTContext &Context, } } -AST_MATCHER_FUNCTION_P(StatementMatcher, isConstRefReturningMethodCall, +AST_MATCHER_FUNCTION_P(StatementMatcher, isRefReturningMethodCall, std::vector, ExcludedContainerTypes) { // Match method call expressions where the `this` argument is only used as - // const, this will be checked in `check()` part. This returned const - // reference is highly likely to outlive the local const reference of the - // variable being declared. The assumption is that the const reference being - // returned either points to a global static variable or to a member of the - // called object. + // const, this will be checked in `check()` part. This returned reference is + // highly likely to outlive the local const reference of the variable being + // declared. The assumption is that the reference being returned either points + // to a global static variable or to a member of the called object. const auto MethodDecl = - cxxMethodDecl(returns(hasCanonicalType(matchers::isReferenceToConst( + cxxMethodDecl(returns(hasCanonicalType(referenceType( .bind(MethodDeclId); const auto ReceiverExpr = ignoringParenImpCasts(declRefExpr(to(varDecl().bind(ObjectArgId; @@ -121,7 +120,7 @@ AST_MATCHER_FUNCTION_P(StatementMatcher, initializerReturnsReferenceToConst, declRefExpr(to(varDecl(hasLocalStorage()).bind(OldVarDeclId))); return expr( anyOf(isConstRefReturningFunctionCall(), -isConstRefReturningMethodCall(ExcludedContainerTypes), +isRefReturningMethodCall(ExcludedContainerTypes), ignoringImpCasts(OldVarDeclRef), ignoringImpCasts(unaryOperator(hasOperatorName("&"), hasUnaryOperand(OldVarDeclRef); @@ -259,9 +258,9 @@ void UnnecessaryCopyInitialization::registerMatchers(MatchFinder *Finder) { .bind("blockStmt"); }; - Finder->addMatcher(LocalVarCopiedFrom(anyOf(isConstRefReturningFunctionCall(), - isConstRefReturningMethodCall( - ExcludedContainerTypes))), + Finder->addMatcher(LocalVarCopiedFrom(anyOf( + isConstRefReturningFunctionCall(), + isRefReturningMethodCall(ExcludedContainerTypes))), this); Finder->addMatcher(LocalVarCopiedFrom(declRefExpr( diff --git a/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp b/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp index a48e45e135681..4ee8a3628061b 100644 --- a/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp +++ b/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp @@ -36,6 +36,111 @@ void extractNodesByIdTo(ArrayRef Matches, StringRef ID, Nodes.insert(Match.getNodeAs(ID)); } +// If `D` has a const-qualified overload with otherwise identical +// ref-qualifiers, returns that overload. +const CXXMethodDecl *findConstOverload(const CXXMethodDecl &D) { + assert(!D.isConst()); + + DeclContext::lookup_result lookup_result = + D.getParent()->lookup(D.getNameInfo().getName()); + if (lookup_result.isSingleResult()) { +// No overload. +return nullptr; + } + for (const Decl *overload : lookup_result) { +const CXXMethodDecl *candidate = dyn_cast(overload); +if (candidate && !candidate->isDeleted() && candidate->isConst() && +candidate->getRefQualifier() == D.getRefQualifier()) { + return candidate; +} + } + return nullptr; +} + +// Returns true
[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)
ChuanqiXu9 wrote: > Just a note, I am building on Windows with MSVC cl.exe and ninja and get this: > > ``` > C:\Program Files\Microsoft Visual > Studio\2022\Community\VC\Tools\MSVC\14.39.33519\include\memory(3138): error > C2027: use of undefined type 'clang::clangd::ProjectModules' > ``` > > While building ConfigCompile.cpp.obj, I was able to solve it by adding > `#include "ProjectModules.h"` into `ConfigCompile.h` before `#include > "GlobalCompilationDatabase.h"`. > > Likewise with `BackgroundIndexLoader.cpp.obj` and adding to > `index\background.h`, it appears any time `GlobalCompilationDatabase.h` is > included that `ProjectModules.h` would need to be included first. It also > seems like `ProjectModules.h` cannot be included in > `GlobalCompilationDatabase.h` due to a circular dependency. I am still > building so there might be similar issues somewhere else in the codebase but > this is the base issue. > > Not sure how to resolve other than adding a `#include` everywhere, seems like > there an issue with include order on MSVC or something. I can't reproduce this. I can't find `ConfigCompile.h` even. But I made some changes about the interface to the patch from the suggestion of @kadircet . So I guess maybe it worth a new try. https://github.com/llvm/llvm-project/pull/66462 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc] [llvm] [AMDGPU] Implement variadic functions by IR lowering (PR #93362)
@@ -0,0 +1,1037 @@ +//===-- ExpandVariadicsPass.cpp *- C++ -*-=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This is an optimization pass for variadic functions. If called from codegen, +// it can serve as the implementation of variadic functions for a given target. +// +// The strategy is to turn the ... part of a variadic function into a va_list +// and fix up the call sites. The majority of the pass is target independent. +// The exceptions are the va_list type itself and the rules for where to store +// variables in memory such that va_arg can iterate over them given a va_list. +// +// The majority of the plumbing is splitting the variadic function into a +// single basic block that packs the variadic arguments into a va_list and +// a second function that does the work of the original. That packing is +// exactly what is done by va_start. Further, the transform from ... to va_list +// replaced va_start with an operation to copy a va_list from the new argument, +// which is exactly a va_copy. This is useful for reducing target-dependence. +// +// A va_list instance is a forward iterator, where the primary operation va_arg +// is dereference-then-increment. This interface forces significant convergent +// evolution between target specific implementations. The variation in runtime +// data layout is limited to that representable by the iterator, parameterised +// by the type passed to the va_arg instruction. +// +// Therefore the majority of the target specific subtlety is packing arguments +// into a stack allocated buffer such that a va_list can be initialised with it +// and the va_arg expansion for the target will find the arguments at runtime. +// +// The aggregate effect is to unblock other transforms, most critically the +// general purpose inliner. Known calls to variadic functions become zero cost. +// +// Consistency with clang is primarily tested by emitting va_arg using clang +// then expanding the variadic functions using this pass, followed by trying +// to constant fold the functions to no-ops. +// +// Target specific behaviour is tested in IR - mainly checking that values are +// put into positions in call frames that make sense for that particular target. +// +// There is one "clever" invariant in use. va_start intrinsics that are not +// within a varidic functions are an error in the IR verifier. When this +// transform moves blocks from a variadic function into a fixed arity one, it +// moves va_start intrinsics along with everything else. That means that the +// va_start intrinsics that need to be rewritten to use the trailing argument +// are exactly those that are in non-variadic functions so no further state +// is needed to distinguish those that need to be rewritten. +// +//===--===// + +#include "llvm/Transforms/IPO/ExpandVariadics.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/InitializePasses.h" +#include "llvm/Pass.h" +#include "llvm/Passes/OptimizationLevel.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/TargetParser/Triple.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" + +#define DEBUG_TYPE "expand-variadics" + +using namespace llvm; + +namespace { + +cl::opt ExpandVariadicsModeOption( +DEBUG_TYPE "-override", cl::desc("Override the behaviour of " DEBUG_TYPE), +cl::init(ExpandVariadicsMode::Unspecified), +cl::values(clEnumValN(ExpandVariadicsMode::Unspecified, "unspecified", + "Use the implementation defaults"), + clEnumValN(ExpandVariadicsMode::Disable, "disable", + "Disable the pass entirely"), + clEnumValN(ExpandVariadicsMode::Optimize, "optimize", + "Optimise without changing ABI"), + clEnumValN(ExpandVariadicsMode::Lowering, "lowering", + "Change variadic calling convention"))); + +bool commandLineOverride() { + return ExpandVariadicsModeOption != ExpandVariadicsMode::Unspecified; +} + +// Instances of this class encapsulate the target-dependant behaviour as a +// function of triple. Implementing a new ABI is adding a case to the switch +// in create(llvm::Triple) at the end of this file. +class VariadicABIInfo { +protected: + VariadicABIInfo() {} + +public: + static std::unique_ptr create(llvm::Triple const &Triple); arsenm wrote: const always to the left. East const is weird https://github.com/llvm/llvm-proj
[clang] 86295dc - Revert "[Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (#91879)" (#94597)
Author: bgra8 Date: 2024-06-06T11:46:33+02:00 New Revision: 86295dc197db2f08f4eb582ed1026a8f74ac3338 URL: https://github.com/llvm/llvm-project/commit/86295dc197db2f08f4eb582ed1026a8f74ac3338 DIFF: https://github.com/llvm/llvm-project/commit/86295dc197db2f08f4eb582ed1026a8f74ac3338.diff LOG: Revert "[Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (#91879)" (#94597) This depends on https://github.com/llvm/llvm-project/pull/92527 which needs to be reverted due to https://github.com/llvm/llvm-project/pull/92527#issuecomment-2149120420. This reverts commit 905b402a5d8f1490d668f40942390ebd6e87aa8f. Co-authored-by: Bogdan Graur Added: Modified: clang/lib/AST/ParentMap.cpp clang/lib/Analysis/CFG.cpp clang/lib/Sema/SemaExpr.cpp clang/lib/StaticAnalyzer/Core/ExprEngine.cpp clang/test/Analysis/cxx-uninitialized-object.cpp clang/test/Analysis/lifetime-extended-regions.cpp Removed: diff --git a/clang/lib/AST/ParentMap.cpp b/clang/lib/AST/ParentMap.cpp index 534793b837bbb..3d6a1cc84c7b1 100644 --- a/clang/lib/AST/ParentMap.cpp +++ b/clang/lib/AST/ParentMap.cpp @@ -97,22 +97,6 @@ static void BuildParentMap(MapTy& M, Stmt* S, BuildParentMap(M, SubStmt, OVMode); } break; - case Stmt::CXXDefaultArgExprClass: -if (auto *Arg = dyn_cast(S)) { - if (Arg->hasRewrittenInit()) { -M[Arg->getExpr()] = S; -BuildParentMap(M, Arg->getExpr(), OVMode); - } -} -break; - case Stmt::CXXDefaultInitExprClass: -if (auto *Init = dyn_cast(S)) { - if (Init->hasRewrittenInit()) { -M[Init->getExpr()] = S; -BuildParentMap(M, Init->getExpr(), OVMode); - } -} -break; default: for (Stmt *SubStmt : S->children()) { if (SubStmt) { diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index 02317257c2740..64e6155de090c 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -556,10 +556,6 @@ class CFGBuilder { private: // Visitors to walk an AST and construct the CFG. - CFGBlock *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Default, - AddStmtChoice asc); - CFGBlock *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Default, -AddStmtChoice asc); CFGBlock *VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc); CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc); CFGBlock *VisitAttributedStmt(AttributedStmt *A, AddStmtChoice asc); @@ -2258,10 +2254,16 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc, asc, ExternallyDestructed); case Stmt::CXXDefaultArgExprClass: - return VisitCXXDefaultArgExpr(cast(S), asc); - case Stmt::CXXDefaultInitExprClass: - return VisitCXXDefaultInitExpr(cast(S), asc); + // FIXME: The expression inside a CXXDefaultArgExpr is owned by the + // called function's declaration, not by the caller. If we simply add + // this expression to the CFG, we could end up with the same Expr + // appearing multiple times (PR13385). + // + // It's likewise possible for multiple CXXDefaultInitExprs for the same + // expression to be used in the same function (through aggregate + // initialization). + return VisitStmt(S, asc); case Stmt::CXXBindTemporaryExprClass: return VisitCXXBindTemporaryExpr(cast(S), asc); @@ -2431,40 +2433,6 @@ CFGBlock *CFGBuilder::VisitChildren(Stmt *S) { return B; } -CFGBlock *CFGBuilder::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Arg, - AddStmtChoice asc) { - if (Arg->hasRewrittenInit()) { -if (asc.alwaysAdd(*this, Arg)) { - autoCreateBlock(); - appendStmt(Block, Arg); -} -return VisitStmt(Arg->getExpr(), asc); - } - - // We can't add the default argument if it's not rewritten because the - // expression inside a CXXDefaultArgExpr is owned by the called function's - // declaration, not by the caller, we could end up with the same expression - // appearing multiple times. - return VisitStmt(Arg, asc); -} - -CFGBlock *CFGBuilder::VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Init, - AddStmtChoice asc) { - if (Init->hasRewrittenInit()) { -if (asc.alwaysAdd(*this, Init)) { - autoCreateBlock(); - appendStmt(Block, Init); -} -return VisitStmt(Init->getExpr(), asc); - } - - // We can't add the default initializer if it's not rewritten because multiple - // CXXDefaultInitExprs for the same sub-expression to be used in the same - // function (through aggregate initialization). we could end up with the same - // expression appearing multiple times. - return VisitStmt(Init, asc); -} - CFGBlock *CFGBuilder::VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc) {
[clang] Revert "[Analyzer][CFG] Correctly handle rebuilt default arg and default init expression (#91879)" (PR #94597)
https://github.com/bgra8 closed https://github.com/llvm/llvm-project/pull/94597 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libc] [llvm] [AMDGPU] Implement variadic functions by IR lowering (PR #93362)
@@ -0,0 +1,1037 @@ +//===-- ExpandVariadicsPass.cpp *- C++ -*-=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// +// +// This is an optimization pass for variadic functions. If called from codegen, +// it can serve as the implementation of variadic functions for a given target. +// +// The strategy is to turn the ... part of a variadic function into a va_list +// and fix up the call sites. The majority of the pass is target independent. +// The exceptions are the va_list type itself and the rules for where to store +// variables in memory such that va_arg can iterate over them given a va_list. +// +// The majority of the plumbing is splitting the variadic function into a +// single basic block that packs the variadic arguments into a va_list and +// a second function that does the work of the original. That packing is +// exactly what is done by va_start. Further, the transform from ... to va_list +// replaced va_start with an operation to copy a va_list from the new argument, +// which is exactly a va_copy. This is useful for reducing target-dependence. +// +// A va_list instance is a forward iterator, where the primary operation va_arg +// is dereference-then-increment. This interface forces significant convergent +// evolution between target specific implementations. The variation in runtime +// data layout is limited to that representable by the iterator, parameterised +// by the type passed to the va_arg instruction. +// +// Therefore the majority of the target specific subtlety is packing arguments +// into a stack allocated buffer such that a va_list can be initialised with it +// and the va_arg expansion for the target will find the arguments at runtime. +// +// The aggregate effect is to unblock other transforms, most critically the +// general purpose inliner. Known calls to variadic functions become zero cost. +// +// Consistency with clang is primarily tested by emitting va_arg using clang +// then expanding the variadic functions using this pass, followed by trying +// to constant fold the functions to no-ops. +// +// Target specific behaviour is tested in IR - mainly checking that values are +// put into positions in call frames that make sense for that particular target. +// +// There is one "clever" invariant in use. va_start intrinsics that are not +// within a varidic functions are an error in the IR verifier. When this +// transform moves blocks from a variadic function into a fixed arity one, it +// moves va_start intrinsics along with everything else. That means that the +// va_start intrinsics that need to be rewritten to use the trailing argument +// are exactly those that are in non-variadic functions so no further state +// is needed to distinguish those that need to be rewritten. +// +//===--===// + +#include "llvm/Transforms/IPO/ExpandVariadics.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/InitializePasses.h" +#include "llvm/Pass.h" +#include "llvm/Passes/OptimizationLevel.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/TargetParser/Triple.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" + +#define DEBUG_TYPE "expand-variadics" + +using namespace llvm; + +namespace { + +cl::opt ExpandVariadicsModeOption( +DEBUG_TYPE "-override", cl::desc("Override the behaviour of " DEBUG_TYPE), +cl::init(ExpandVariadicsMode::Unspecified), +cl::values(clEnumValN(ExpandVariadicsMode::Unspecified, "unspecified", + "Use the implementation defaults"), + clEnumValN(ExpandVariadicsMode::Disable, "disable", + "Disable the pass entirely"), + clEnumValN(ExpandVariadicsMode::Optimize, "optimize", + "Optimise without changing ABI"), + clEnumValN(ExpandVariadicsMode::Lowering, "lowering", + "Change variadic calling convention"))); + +bool commandLineOverride() { + return ExpandVariadicsModeOption != ExpandVariadicsMode::Unspecified; +} + +// Instances of this class encapsulate the target-dependant behaviour as a +// function of triple. Implementing a new ABI is adding a case to the switch +// in create(llvm::Triple) at the end of this file. +class VariadicABIInfo { +protected: + VariadicABIInfo() {} + +public: + static std::unique_ptr create(llvm::Triple const &Triple); + + // Allow overriding whether the pass runs on a per-target basis + virtual bool enableForTarget() = 0; + +
[clang] 026fbdf - [clang][Interp] Handle one-past-the-end pointers in SubPtr
Author: Timm Bäder Date: 2024-06-06T11:48:31+02:00 New Revision: 026fbdf934d4adc8b6abe544ba1bcfa3b64293ac URL: https://github.com/llvm/llvm-project/commit/026fbdf934d4adc8b6abe544ba1bcfa3b64293ac DIFF: https://github.com/llvm/llvm-project/commit/026fbdf934d4adc8b6abe544ba1bcfa3b64293ac.diff LOG: [clang][Interp] Handle one-past-the-end pointers in SubPtr Added: Modified: clang/lib/AST/Interp/Interp.h clang/test/AST/Interp/arrays.cpp Removed: diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index 17f05548a190..1248eeb79cbf 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -1773,8 +1773,10 @@ inline bool SubPtr(InterpState &S, CodePtr OpPC) { return true; } - T A = T::from(LHS.getIndex()); - T B = T::from(RHS.getIndex()); + T A = LHS.isElementPastEnd() ? T::from(LHS.getNumElems()) + : T::from(LHS.getIndex()); + T B = RHS.isElementPastEnd() ? T::from(RHS.getNumElems()) + : T::from(RHS.getIndex()); return AddSubMulHelper(S, OpPC, A.bitWidth(), A, B); } diff --git a/clang/test/AST/Interp/arrays.cpp b/clang/test/AST/Interp/arrays.cpp index dd5064d993e6..6146d41c5ff5 100644 --- a/clang/test/AST/Interp/arrays.cpp +++ b/clang/test/AST/Interp/arrays.cpp @@ -609,3 +609,9 @@ namespace ArrayMemberAccess { bool cond = a->x; } } + +namespace OnePastEndSub { + struct A {}; + constexpr A a[3][3]; + constexpr int diff 2 = &a[1][3] - &a[1][0]; /// Used to crash. +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] e285818 - Revert "[serialization] no transitive decl change (#92083)"
Author: Chuanqi Xu Date: 2024-06-06T17:49:59+08:00 New Revision: e2858189bd99e6914dc2f63ab55b053a74b4e58b URL: https://github.com/llvm/llvm-project/commit/e2858189bd99e6914dc2f63ab55b053a74b4e58b DIFF: https://github.com/llvm/llvm-project/commit/e2858189bd99e6914dc2f63ab55b053a74b4e58b.diff LOG: Revert "[serialization] no transitive decl change (#92083)" This reverts commit 97c866f6c86456b3316006e6beff47e68a81c00a. This fails on 32bit machines. See https://github.com/llvm/llvm-project/pull/92083 Added: Modified: clang/include/clang/AST/DeclBase.h clang/include/clang/AST/DeclID.h clang/include/clang/Serialization/ASTBitCodes.h clang/include/clang/Serialization/ASTReader.h clang/include/clang/Serialization/ModuleFile.h clang/include/clang/Serialization/ModuleManager.h clang/lib/AST/DeclBase.cpp clang/lib/Serialization/ASTReader.cpp clang/lib/Serialization/ASTReaderDecl.cpp clang/lib/Serialization/ASTWriter.cpp clang/lib/Serialization/ModuleFile.cpp Removed: clang/test/Modules/no-transitive-decls-change.cppm diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 5f19af1891b7..600ce73c7f01 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -708,7 +708,10 @@ class alignas(8) Decl { /// Set the owning module ID. This may only be called for /// deserialized Decls. - void setOwningModuleID(unsigned ID); + void setOwningModuleID(unsigned ID) { +assert(isFromASTFile() && "Only works on a deserialized declaration"); +*((unsigned*)this - 2) = ID; + } public: /// Determine the availability of the given declaration. @@ -781,11 +784,19 @@ class alignas(8) Decl { /// Retrieve the global declaration ID associated with this /// declaration, which specifies where this Decl was loaded from. - GlobalDeclID getGlobalID() const; + GlobalDeclID getGlobalID() const { +if (isFromASTFile()) + return (*((const GlobalDeclID *)this - 1)); +return GlobalDeclID(); + } /// Retrieve the global ID of the module that owns this particular /// declaration. - unsigned getOwningModuleID() const; + unsigned getOwningModuleID() const { +if (isFromASTFile()) + return *((const unsigned*)this - 2); +return 0; + } private: Module *getOwningModuleSlow() const; diff --git a/clang/include/clang/AST/DeclID.h b/clang/include/clang/AST/DeclID.h index 32d2ed41a374..614ba06b6386 100644 --- a/clang/include/clang/AST/DeclID.h +++ b/clang/include/clang/AST/DeclID.h @@ -19,8 +19,6 @@ #include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/iterator.h" -#include - namespace clang { /// Predefined declaration IDs. @@ -109,16 +107,12 @@ class DeclIDBase { /// /// DeclID should only be used directly in serialization. All other users /// should use LocalDeclID or GlobalDeclID. - using DeclID = uint64_t; + using DeclID = uint32_t; protected: DeclIDBase() : ID(PREDEF_DECL_NULL_ID) {} explicit DeclIDBase(DeclID ID) : ID(ID) {} - explicit DeclIDBase(unsigned LocalID, unsigned ModuleFileIndex) { -ID = (DeclID)LocalID | ((DeclID)ModuleFileIndex << 32); - } - public: DeclID get() const { return ID; } @@ -130,10 +124,6 @@ class DeclIDBase { bool isInvalid() const { return ID == PREDEF_DECL_NULL_ID; } - unsigned getModuleFileIndex() const { return ID >> 32; } - - unsigned getLocalDeclIndex() const; - friend bool operator==(const DeclIDBase &LHS, const DeclIDBase &RHS) { return LHS.ID == RHS.ID; } @@ -166,9 +156,6 @@ class LocalDeclID : public DeclIDBase { LocalDeclID(PredefinedDeclIDs ID) : Base(ID) {} explicit LocalDeclID(DeclID ID) : Base(ID) {} - explicit LocalDeclID(unsigned LocalID, unsigned ModuleFileIndex) - : Base(LocalID, ModuleFileIndex) {} - LocalDeclID &operator++() { ++ID; return *this; @@ -188,9 +175,6 @@ class GlobalDeclID : public DeclIDBase { GlobalDeclID() : Base() {} explicit GlobalDeclID(DeclID ID) : Base(ID) {} - explicit GlobalDeclID(unsigned LocalID, unsigned ModuleFileIndex) - : Base(LocalID, ModuleFileIndex) {} - // For DeclIDIterator to be able to convert a GlobalDeclID // to a LocalDeclID. explicit operator LocalDeclID() const { return LocalDeclID(this->ID); } diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 3f3fb8869f5f..f59ff6af4c76 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -255,12 +255,6 @@ class DeclOffset { } }; -// The unaligned decl ID used in the Blobs of bistreams. -using unaligned_decl_id_t = -llvm::support::detail::packed_endian_specific_integral< -serialization::DeclID, llvm::endianness::native, -llvm::support::unaligned>; - /// The number of predefined p
[clang] [amdgpu] Pass variadic arguments without splitting (PR #94083)
arsenm wrote: > @arsenm You're right about passing larger things indirectly. I'm intending to > land this as-is, with the types inlined, as that unblocks #93362. I'm nervous > that the extra pointer indirection will hit the same memory error that > tweaking codegen in that patch hits (it's a similar sort of pattern to the > top level argument passing) and wish to postpone that until there is a > working baseline. I do think we need to revisit some threshold at some point. We should use byref for anything that's most likely to hit the stack anyway https://github.com/llvm/llvm-project/pull/94083 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [amdgpu] Pass variadic arguments without splitting (PR #94083)
@@ -0,0 +1,293 @@ +// REQUIRES: amdgpu-registered-target +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature +// RUN: %clang_cc1 -cc1 -std=c23 -triple amdgcn-amd-amdhsa -emit-llvm -O1 %s -o - | FileCheck %s + +void sink_0(...); +void sink_1(int, ...); +void sink_2(double, int, ...); + +// Simple scalar values + +// CHECK-LABEL: define {{[^@]+}}@zero_varargs +// CHECK-SAME: (i32 noundef [[F0:%.*]], double noundef [[F1:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT:tail call void (...) @sink_0() #[[ATTR2:[0-9]+]] +// CHECK-NEXT:tail call void (i32, ...) @sink_1(i32 noundef [[F0]]) #[[ATTR2]] +// CHECK-NEXT:tail call void (double, i32, ...) @sink_2(double noundef [[F1]], i32 noundef [[F0]]) #[[ATTR2]] +// CHECK-NEXT:ret void +// +void zero_varargs(int f0, double f1) +{ + sink_0(); + sink_1(f0); + sink_2(f1, f0); +} + +// CHECK-LABEL: define {{[^@]+}}@one_i32 +// CHECK-SAME: (i32 noundef [[F0:%.*]], double noundef [[F1:%.*]], i32 noundef [[V0:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT:tail call void (...) @sink_0(i32 noundef [[V0]]) #[[ATTR2]] +// CHECK-NEXT:tail call void (i32, ...) @sink_1(i32 noundef [[F0]], i32 noundef [[V0]]) #[[ATTR2]] +// CHECK-NEXT:tail call void (double, i32, ...) @sink_2(double noundef [[F1]], i32 noundef [[F0]], i32 noundef [[V0]]) #[[ATTR2]] +// CHECK-NEXT:ret void +// +void one_i32(int f0, double f1, int v0) +{ + sink_0(v0); + sink_1(f0, v0); + sink_2(f1, f0, v0); +} + +// CHECK-LABEL: define {{[^@]+}}@one_ptr +// CHECK-SAME: (i32 noundef [[F0:%.*]], double noundef [[F1:%.*]], ptr noundef [[V0:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT:tail call void (...) @sink_0(ptr noundef [[V0]]) #[[ATTR2]] +// CHECK-NEXT:tail call void (i32, ...) @sink_1(i32 noundef [[F0]], ptr noundef [[V0]]) #[[ATTR2]] +// CHECK-NEXT:tail call void (double, i32, ...) @sink_2(double noundef [[F1]], i32 noundef [[F0]], ptr noundef [[V0]]) #[[ATTR2]] +// CHECK-NEXT:ret void +// +void one_ptr(int f0, double f1, void* v0) +{ + sink_0(v0); + sink_1(f0, v0); + sink_2(f1, f0, v0); +} + +// CHECK-LABEL: define {{[^@]+}}@one_f64 +// CHECK-SAME: (i32 noundef [[F0:%.*]], double noundef [[F1:%.*]], double noundef [[V0:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT:tail call void (...) @sink_0(double noundef [[V0]]) #[[ATTR2]] +// CHECK-NEXT:tail call void (i32, ...) @sink_1(i32 noundef [[F0]], double noundef [[V0]]) #[[ATTR2]] +// CHECK-NEXT:tail call void (double, i32, ...) @sink_2(double noundef [[F1]], i32 noundef [[F0]], double noundef [[V0]]) #[[ATTR2]] +// CHECK-NEXT:ret void +// +void one_f64(int f0, double f1, double v0) +{ + sink_0(v0); + sink_1(f0, v0); + sink_2(f1, f0, v0); +} + + +// C has various type promotion rules for variadics + +// CHECK-LABEL: define {{[^@]+}}@one_i8 +// CHECK-SAME: (i32 noundef [[F0:%.*]], double noundef [[F1:%.*]], i8 noundef signext [[V0:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT:[[CONV:%.*]] = sext i8 [[V0]] to i32 +// CHECK-NEXT:tail call void (...) @sink_0(i32 noundef [[CONV]]) #[[ATTR2]] +// CHECK-NEXT:tail call void (i32, ...) @sink_1(i32 noundef [[F0]], i32 noundef [[CONV]]) #[[ATTR2]] +// CHECK-NEXT:tail call void (double, i32, ...) @sink_2(double noundef [[F1]], i32 noundef [[F0]], i32 noundef [[CONV]]) #[[ATTR2]] +// CHECK-NEXT:ret void +// +void one_i8(int f0, double f1, char v0) +{ + sink_0(v0); + sink_1(f0, v0); + sink_2(f1, f0, v0); +} + +// CHECK-LABEL: define {{[^@]+}}@one_i16 +// CHECK-SAME: (i32 noundef [[F0:%.*]], double noundef [[F1:%.*]], i16 noundef signext [[V0:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT:[[CONV:%.*]] = sext i16 [[V0]] to i32 +// CHECK-NEXT:tail call void (...) @sink_0(i32 noundef [[CONV]]) #[[ATTR2]] +// CHECK-NEXT:tail call void (i32, ...) @sink_1(i32 noundef [[F0]], i32 noundef [[CONV]]) #[[ATTR2]] +// CHECK-NEXT:tail call void (double, i32, ...) @sink_2(double noundef [[F1]], i32 noundef [[F0]], i32 noundef [[CONV]]) #[[ATTR2]] +// CHECK-NEXT:ret void +// +void one_i16(int f0, double f1, short v0) +{ + sink_0(v0); + sink_1(f0, v0); + sink_2(f1, f0, v0); +} + +// CHECK-LABEL: define {{[^@]+}}@one_f32 +// CHECK-SAME: (i32 noundef [[F0:%.*]], double noundef [[F1:%.*]], float noundef [[V0:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT:[[CONV:%.*]] = fpext float [[V0]] to double +// CHECK-NEXT:tail call void (...) @sink_0(double noundef [[CONV]]) #[[ATTR2]] +// CHECK-NEXT:tail call void (i32, ...) @sink_1(i32 noundef [[F0]], double noundef [[CONV]]) #[[ATTR2]] +// CHECK-NEXT:tail call void (double, i32, ...) @sink_2(double noundef [[F1]], i32 noundef [[F0]], double noundef [[C
[clang] Revert "Reapply "[Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer" (#92527)" (PR #94600)
https://github.com/bgra8 created https://github.com/llvm/llvm-project/pull/94600 Reverting due to https://github.com/llvm/llvm-project/pull/92527#issuecomment-2149120420. This reverts commit f049d72ac2bcc40fd91d4e95148658021fb24bf1. >From fbaa1ce73030c456c62ab8b2d002b8f04b6913a7 Mon Sep 17 00:00:00 2001 From: Bogdan Graur Date: Thu, 6 Jun 2024 09:48:36 + Subject: [PATCH] Revert "Reapply "[Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer" (#92527)" Reverting due to https://github.com/llvm/llvm-project/pull/92527#issuecomment-2149120420. This reverts commit f049d72ac2bcc40fd91d4e95148658021fb24bf1. --- .../clang/Basic/DiagnosticSemaKinds.td| 6 ++ clang/lib/Sema/SemaExpr.cpp | 31 ++-- clang/lib/Sema/SemaExprCXX.cpp| 3 + clang/lib/Sema/SemaInit.cpp | 19 - clang/lib/Sema/TreeTransform.h| 12 +-- clang/test/AST/ast-dump-default-init-json.cpp | 6 +- clang/test/AST/ast-dump-default-init.cpp | 2 +- .../Analysis/lifetime-extended-regions.cpp| 9 +-- clang/test/CXX/drs/cwg16xx.cpp| 2 + clang/test/CXX/drs/cwg18xx.cpp| 19 ++--- clang/test/CXX/special/class.temporary/p6.cpp | 34 - clang/test/SemaCXX/constexpr-default-arg.cpp | 4 +- .../cxx11-default-member-initializers.cpp | 74 --- clang/test/SemaCXX/eval-crashes.cpp | 6 +- clang/www/cxx_dr_status.html | 2 +- 15 files changed, 61 insertions(+), 168 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 87745140cb0eb..9f0b6f5a36389 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10082,6 +10082,12 @@ def warn_new_dangling_initializer_list : Warning< "the allocated initializer list}0 " "will be destroyed at the end of the full-expression">, InGroup; +def warn_unsupported_lifetime_extension : Warning< + "lifetime extension of " + "%select{temporary|backing array of initializer list}0 created " + "by aggregate initialization using a default member initializer " + "is not yet supported; lifetime of %select{temporary|backing array}0 " + "will end at the end of the full-expression">, InGroup; // For non-floating point, expressions of the form x == x or x != x // should result in a warning, since these always evaluate to a constant. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index d8c77e3e0a5cd..76145f291887c 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -5572,9 +5572,10 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, Res = Immediate.TransformInitializer(Param->getInit(), /*NotCopy=*/false); }); - if (Res.isUsable()) -Res = ConvertParamDefaultArgument(Param, Res.get(), - Res.get()->getBeginLoc()); + if (Res.isInvalid()) +return ExprError(); + Res = ConvertParamDefaultArgument(Param, Res.get(), +Res.get()->getBeginLoc()); if (Res.isInvalid()) return ExprError(); Init = Res.get(); @@ -5610,7 +5611,7 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { Expr *Init = nullptr; bool NestedDefaultChecking = isCheckingDefaultArgumentOrInitializer(); - bool InLifetimeExtendingContext = isInLifetimeExtendingContext(); + EnterExpressionEvaluationContext EvalContext( *this, ExpressionEvaluationContext::PotentiallyEvaluated, Field); @@ -5645,35 +5646,19 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { ImmediateCallVisitor V(getASTContext()); if (!NestedDefaultChecking) V.TraverseDecl(Field); - - // CWG1815 - // Support lifetime extension of temporary created by aggregate - // initialization using a default member initializer. We should always rebuild - // the initializer if it contains any temporaries (if the initializer - // expression is an ExprWithCleanups). Then make sure the normal lifetime - // extension code recurses into the default initializer and does lifetime - // extension when warranted. - bool ContainsAnyTemporaries = - isa_and_present(Field->getInClassInitializer()); - if (V.HasImmediateCalls || InLifetimeExtendingContext || - ContainsAnyTemporaries) { + if (V.HasImmediateCalls) { ExprEvalContexts.back().DelayedDefaultInitializationContext = {Loc, Field, CurContext}; ExprEvalContexts.back().IsCurrentlyCheckingDefaultArgumentOrInitializer = NestedDefaultChecking; -// Pass down lifetime extending flag, and collect temporaries in -// Create
[clang] Revert "Reapply "[Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer" (#92527)" (PR #94600)
llvmbot wrote: @llvm/pr-subscribers-clang Author: None (bgra8) Changes Reverting due to https://github.com/llvm/llvm-project/pull/92527#issuecomment-2149120420. This reverts commit f049d72ac2bcc40fd91d4e95148658021fb24bf1. --- Full diff: https://github.com/llvm/llvm-project/pull/94600.diff 15 Files Affected: - (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+6) - (modified) clang/lib/Sema/SemaExpr.cpp (+8-23) - (modified) clang/lib/Sema/SemaExprCXX.cpp (+3) - (modified) clang/lib/Sema/SemaInit.cpp (+18-1) - (modified) clang/lib/Sema/TreeTransform.h (+4-8) - (modified) clang/test/AST/ast-dump-default-init-json.cpp (+3-3) - (modified) clang/test/AST/ast-dump-default-init.cpp (+1-1) - (modified) clang/test/Analysis/lifetime-extended-regions.cpp (+4-5) - (modified) clang/test/CXX/drs/cwg16xx.cpp (+2) - (modified) clang/test/CXX/drs/cwg18xx.cpp (+5-14) - (modified) clang/test/CXX/special/class.temporary/p6.cpp (-34) - (modified) clang/test/SemaCXX/constexpr-default-arg.cpp (+2-2) - (modified) clang/test/SemaCXX/cxx11-default-member-initializers.cpp (-74) - (modified) clang/test/SemaCXX/eval-crashes.cpp (+4-2) - (modified) clang/www/cxx_dr_status.html (+1-1) ``diff diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 87745140cb0eb..9f0b6f5a36389 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10082,6 +10082,12 @@ def warn_new_dangling_initializer_list : Warning< "the allocated initializer list}0 " "will be destroyed at the end of the full-expression">, InGroup; +def warn_unsupported_lifetime_extension : Warning< + "lifetime extension of " + "%select{temporary|backing array of initializer list}0 created " + "by aggregate initialization using a default member initializer " + "is not yet supported; lifetime of %select{temporary|backing array}0 " + "will end at the end of the full-expression">, InGroup; // For non-floating point, expressions of the form x == x or x != x // should result in a warning, since these always evaluate to a constant. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index d8c77e3e0a5cd..76145f291887c 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -5572,9 +5572,10 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, Res = Immediate.TransformInitializer(Param->getInit(), /*NotCopy=*/false); }); - if (Res.isUsable()) -Res = ConvertParamDefaultArgument(Param, Res.get(), - Res.get()->getBeginLoc()); + if (Res.isInvalid()) +return ExprError(); + Res = ConvertParamDefaultArgument(Param, Res.get(), +Res.get()->getBeginLoc()); if (Res.isInvalid()) return ExprError(); Init = Res.get(); @@ -5610,7 +5611,7 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { Expr *Init = nullptr; bool NestedDefaultChecking = isCheckingDefaultArgumentOrInitializer(); - bool InLifetimeExtendingContext = isInLifetimeExtendingContext(); + EnterExpressionEvaluationContext EvalContext( *this, ExpressionEvaluationContext::PotentiallyEvaluated, Field); @@ -5645,35 +5646,19 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { ImmediateCallVisitor V(getASTContext()); if (!NestedDefaultChecking) V.TraverseDecl(Field); - - // CWG1815 - // Support lifetime extension of temporary created by aggregate - // initialization using a default member initializer. We should always rebuild - // the initializer if it contains any temporaries (if the initializer - // expression is an ExprWithCleanups). Then make sure the normal lifetime - // extension code recurses into the default initializer and does lifetime - // extension when warranted. - bool ContainsAnyTemporaries = - isa_and_present(Field->getInClassInitializer()); - if (V.HasImmediateCalls || InLifetimeExtendingContext || - ContainsAnyTemporaries) { + if (V.HasImmediateCalls) { ExprEvalContexts.back().DelayedDefaultInitializationContext = {Loc, Field, CurContext}; ExprEvalContexts.back().IsCurrentlyCheckingDefaultArgumentOrInitializer = NestedDefaultChecking; -// Pass down lifetime extending flag, and collect temporaries in -// CreateMaterializeTemporaryExpr when we rewrite the call argument. -keepInLifetimeExtendingContext(); + EnsureImmediateInvocationInDefaultArgs Immediate(*this); ExprResult Res; - -// Rebuild CXXDefaultInitExpr might cause diagnostics. -SFINAETrap Trap(*this); runWithSufficientStackSpace(Loc, [&] { Res = Immediate.TransformInitializer(Field->getInClassIniti
[clang] 7f52e4c - Revert "Reapply "[Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer" (#92527)" (#94600)
Author: bgra8 Date: 2024-06-06T11:59:52+02:00 New Revision: 7f52e4c755fcd02232964f19bb0226878255f274 URL: https://github.com/llvm/llvm-project/commit/7f52e4c755fcd02232964f19bb0226878255f274 DIFF: https://github.com/llvm/llvm-project/commit/7f52e4c755fcd02232964f19bb0226878255f274.diff LOG: Revert "Reapply "[Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer" (#92527)" (#94600) Reverting due to https://github.com/llvm/llvm-project/pull/92527#issuecomment-2149120420. This reverts commit f049d72ac2bcc40fd91d4e95148658021fb24bf1. Co-authored-by: Bogdan Graur Added: Modified: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaExpr.cpp clang/lib/Sema/SemaExprCXX.cpp clang/lib/Sema/SemaInit.cpp clang/lib/Sema/TreeTransform.h clang/test/AST/ast-dump-default-init-json.cpp clang/test/AST/ast-dump-default-init.cpp clang/test/Analysis/lifetime-extended-regions.cpp clang/test/CXX/drs/cwg16xx.cpp clang/test/CXX/drs/cwg18xx.cpp clang/test/CXX/special/class.temporary/p6.cpp clang/test/SemaCXX/constexpr-default-arg.cpp clang/test/SemaCXX/cxx11-default-member-initializers.cpp clang/test/SemaCXX/eval-crashes.cpp clang/www/cxx_dr_status.html Removed: diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 87745140cb0eb..9f0b6f5a36389 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10082,6 +10082,12 @@ def warn_new_dangling_initializer_list : Warning< "the allocated initializer list}0 " "will be destroyed at the end of the full-expression">, InGroup; +def warn_unsupported_lifetime_extension : Warning< + "lifetime extension of " + "%select{temporary|backing array of initializer list}0 created " + "by aggregate initialization using a default member initializer " + "is not yet supported; lifetime of %select{temporary|backing array}0 " + "will end at the end of the full-expression">, InGroup; // For non-floating point, expressions of the form x == x or x != x // should result in a warning, since these always evaluate to a constant. diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index d8c77e3e0a5cd..76145f291887c 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -5572,9 +5572,10 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, Res = Immediate.TransformInitializer(Param->getInit(), /*NotCopy=*/false); }); - if (Res.isUsable()) -Res = ConvertParamDefaultArgument(Param, Res.get(), - Res.get()->getBeginLoc()); + if (Res.isInvalid()) +return ExprError(); + Res = ConvertParamDefaultArgument(Param, Res.get(), +Res.get()->getBeginLoc()); if (Res.isInvalid()) return ExprError(); Init = Res.get(); @@ -5610,7 +5611,7 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { Expr *Init = nullptr; bool NestedDefaultChecking = isCheckingDefaultArgumentOrInitializer(); - bool InLifetimeExtendingContext = isInLifetimeExtendingContext(); + EnterExpressionEvaluationContext EvalContext( *this, ExpressionEvaluationContext::PotentiallyEvaluated, Field); @@ -5645,35 +5646,19 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { ImmediateCallVisitor V(getASTContext()); if (!NestedDefaultChecking) V.TraverseDecl(Field); - - // CWG1815 - // Support lifetime extension of temporary created by aggregate - // initialization using a default member initializer. We should always rebuild - // the initializer if it contains any temporaries (if the initializer - // expression is an ExprWithCleanups). Then make sure the normal lifetime - // extension code recurses into the default initializer and does lifetime - // extension when warranted. - bool ContainsAnyTemporaries = - isa_and_present(Field->getInClassInitializer()); - if (V.HasImmediateCalls || InLifetimeExtendingContext || - ContainsAnyTemporaries) { + if (V.HasImmediateCalls) { ExprEvalContexts.back().DelayedDefaultInitializationContext = {Loc, Field, CurContext}; ExprEvalContexts.back().IsCurrentlyCheckingDefaultArgumentOrInitializer = NestedDefaultChecking; -// Pass down lifetime extending flag, and collect temporaries in -// CreateMaterializeTemporaryExpr when we rewrite the call argument. -keepInLifetimeExtendingContext(); + EnsureImmediateInvocationInDefaultArgs Immediate(*this); ExprResult Res; - -// Rebuil
[clang] Revert "Reapply "[Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer" (#92527)" (PR #94600)
https://github.com/bgra8 closed https://github.com/llvm/llvm-project/pull/94600 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [RISCV] Add processor definition for SpacemiT-X60 (PR #94564)
https://github.com/sunshaoce updated https://github.com/llvm/llvm-project/pull/94564 >From 363e29385277c049bc91a86e76ff6f6ae70ceaa9 Mon Sep 17 00:00:00 2001 From: Shao-Ce SUN Date: Thu, 6 Jun 2024 12:05:33 +0800 Subject: [PATCH 1/4] [RISCV] Add processor definition for Spacemit-K1 --- clang/test/Driver/riscv-cpus.c| 12 ++ clang/test/Misc/target-invalid-cpu-note.c | 4 ++-- llvm/lib/Target/RISCV/RISCVProcessors.td | 29 +++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/clang/test/Driver/riscv-cpus.c b/clang/test/Driver/riscv-cpus.c index ff2bd6f7c8ba3..32d7910ab4daa 100644 --- a/clang/test/Driver/riscv-cpus.c +++ b/clang/test/Driver/riscv-cpus.c @@ -31,6 +31,18 @@ // MCPU-XIANGSHAN-NANHU-SAME: "-target-feature" "+zks" "-target-feature" "+zksed" "-target-feature" "+zksh" "-target-feature" "+svinval" // MCPU-XIANGSHAN-NANHU-SAME: "-target-abi" "lp64d" +// RUN: %clang --target=riscv64 -### -c %s 2>&1 -mcpu=spacemit-k1 | FileCheck -check-prefix=MCPU-SPACEMIT-K1 %s +// MCPU-SPACEMIT-K1: "-nostdsysteminc" "-target-cpu" "spacemit-k1" +// MCPU-SPACEMIT-K1-SAME: "-target-feature" "+m" "-target-feature" "+a" "-target-feature" "+f" "-target-feature" "+d" +// MCPU-SPACEMIT-K1-SAME: "-target-feature" "+c" "-target-feature" "+v" "-target-feature" "+zicond" "-target-feature" "+zicsr" +// MCPU-SPACEMIT-K1-SAME: "-target-feature" "+zifencei" "-target-feature" "+zmmul" "-target-feature" "+zfh" +// MCPU-SPACEMIT-K1-SAME: "-target-feature" "+zfhmin" "-target-feature" "+zba" "-target-feature" "+zbb" "-target-feature" "+zbc" +// MCPU-SPACEMIT-K1-SAME: "-target-feature" "+zbkb" "-target-feature" "+zbkc" "-target-feature" "+zbs" "-target-feature" "+zve32f" +// MCPU-SPACEMIT-K1-SAME: "-target-feature" "+zve32x" "-target-feature" "+zve64d" "-target-feature" "+zve64f" "-target-feature" "+zve64x" +// MCPU-SPACEMIT-K1-SAME: "-target-feature" "+zvfh" "-target-feature" "+zvfhmin" +// MCPU-SPACEMIT-K1-SAME: "-target-feature" "+zvl128b" "-target-feature" "+zvl256b" "-target-feature" "+zvl32b" "-target-feature" "+zvl64b" +// MCPU-SPACEMIT-K1-SAME: "-target-abi" "lp64d" + // We cannot check much for -mcpu=native, but it should be replaced by a valid CPU string. // RUN: %clang --target=riscv64 -### -c %s -mcpu=native 2> %t.err || true // RUN: FileCheck --input-file=%t.err -check-prefix=MCPU-NATIVE %s diff --git a/clang/test/Misc/target-invalid-cpu-note.c b/clang/test/Misc/target-invalid-cpu-note.c index 6558fd753d1d1..04e92360fe665 100644 --- a/clang/test/Misc/target-invalid-cpu-note.c +++ b/clang/test/Misc/target-invalid-cpu-note.c @@ -85,7 +85,7 @@ // RUN: not %clang_cc1 -triple riscv64 -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix RISCV64 // RISCV64: error: unknown target CPU 'not-a-cpu' -// RISCV64-NEXT: note: valid target CPU values are: generic-rv64, rocket-rv64, sifive-p450, sifive-p670, sifive-s21, sifive-s51, sifive-s54, sifive-s76, sifive-u54, sifive-u74, sifive-x280, veyron-v1, xiangshan-nanhu{{$}} +// RISCV64-NEXT: note: valid target CPU values are: generic-rv64, rocket-rv64, sifive-p450, sifive-p670, sifive-s21, sifive-s51, sifive-s54, sifive-s76, sifive-u54, sifive-u74, sifive-x280, spacemit-k1, veyron-v1, xiangshan-nanhu{{$}} // RUN: not %clang_cc1 -triple riscv32 -tune-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix TUNE-RISCV32 // TUNE-RISCV32: error: unknown target CPU 'not-a-cpu' @@ -93,4 +93,4 @@ // RUN: not %clang_cc1 -triple riscv64 -tune-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix TUNE-RISCV64 // TUNE-RISCV64: error: unknown target CPU 'not-a-cpu' -// TUNE-RISCV64-NEXT: note: valid target CPU values are: generic-rv64, rocket-rv64, sifive-p450, sifive-p670, sifive-s21, sifive-s51, sifive-s54, sifive-s76, sifive-u54, sifive-u74, sifive-x280, veyron-v1, xiangshan-nanhu, generic, rocket, sifive-7-series{{$}} +// TUNE-RISCV64-NEXT: note: valid target CPU values are: generic-rv64, rocket-rv64, sifive-p450, sifive-p670, sifive-s21, sifive-s51, sifive-s54, sifive-s76, sifive-u54, sifive-u74, sifive-x280, spacemit-k1, veyron-v1, xiangshan-nanhu, generic, rocket, sifive-7-series{{$}} diff --git a/llvm/lib/Target/RISCV/RISCVProcessors.td b/llvm/lib/Target/RISCV/RISCVProcessors.td index 6ebf9f1eb0452..08602e9d06cc9 100644 --- a/llvm/lib/Target/RISCV/RISCVProcessors.td +++ b/llvm/lib/Target/RISCV/RISCVProcessors.td @@ -381,3 +381,32 @@ def XIANGSHAN_NANHU : RISCVProcessorModel<"xiangshan-nanhu", TuneZExtHFusion, TuneZExtWFusion, TuneShiftedZExtWFusion]>; + +def SPACEMIT_K1 : RISCVProcessorModel<"spacemit-k1", + NoSchedModel, + [Feature64Bit, +FeatureStdExtI, +FeatureStdExtM, +
[clang] [clang] Report erroneous floating point results in _Complex math (PR #90588)
tbaederr wrote: Ping https://github.com/llvm/llvm-project/pull/90588 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [llvm] [mlir] [Flang]Fix for changed code at the end of AllocaIP. (PR #92430)
https://github.com/tblah approved this pull request. LGTM if @Meinersbur is happy. It's a shame about the fallout to the clang tests but I can see that would be very difficult to avoid. Thank you for persisting with this difficult patch. https://github.com/llvm/llvm-project/pull/92430 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Reapply "[Clang][CWG1815] Support lifetime extension of temporary created by aggregate initialization using a default member initializer" (PR #92527)
alexfh wrote: > Here's the reproducer: > > ```c++ > struct a { > virtual int *b(); > }; > template struct d : a { > int *b() { new c; } > }; > int *e(a *); > struct f { > char *g; > }; > struct h {}; > struct i { > i(const f &); > i(h); > }; > struct l { > i j = i({.g = ""}); > }; > int *k = e(new d); > struct n : l {}; > int *m = e(new d); > ``` A bit clearer repro: https://gcc.godbolt.org/z/r9EdcoW8G The new clang behavior seems wrong to me. https://github.com/llvm/llvm-project/pull/92527 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [PowerPC] Support -mno-red-zone option (PR #94581)
https://github.com/ecnelises updated https://github.com/llvm/llvm-project/pull/94581 >From 4e078099d8e15fd984ef38435d6f792bbb3d754c Mon Sep 17 00:00:00 2001 From: Qiu Chaofan Date: Thu, 6 Jun 2024 14:06:48 +0800 Subject: [PATCH 1/2] [PowerPC] Support -mno-red-zone option --- clang/lib/Driver/ToolChains/Clang.cpp | 3 +++ clang/test/Driver/flags.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 4e1c52462e584..3a37c05c8b44b 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -2022,6 +2022,9 @@ void Clang::AddPPCTargetArgs(const ArgList &Args, CmdArgs.push_back("-mabi=vec-extabi"); } + if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true)) +CmdArgs.push_back("-disable-red-zone"); + ppc::FloatABI FloatABI = ppc::getPPCFloatABI(D, Args); if (FloatABI == ppc::FloatABI::Soft) { // Floating point operations and argument passing are soft. diff --git a/clang/test/Driver/flags.c b/clang/test/Driver/flags.c index 16b760609c36d..7d2bef63fca3e 100644 --- a/clang/test/Driver/flags.c +++ b/clang/test/Driver/flags.c @@ -33,3 +33,6 @@ // // RUN: %clang --target=riscv64 -### -S -mno-implicit-float %s 2>&1 | FileCheck -check-prefix=TEST11 %s // TEST11: "-no-implicit-float" +// +// RUN: %clang --target=ppc64le -### -S -mno-red-zone %s 2>&1 | FileCheck -check-prefix=TEST12 %s +// TEST12: "-disable-red-zone" >From b8e076e175f42e07a329d2bee4878785f6145288 Mon Sep 17 00:00:00 2001 From: Qiu Chaofan Date: Thu, 6 Jun 2024 18:02:58 +0800 Subject: [PATCH 2/2] Add noredzone LLC test --- llvm/test/CodeGen/PowerPC/noredzone.ll | 513 + 1 file changed, 513 insertions(+) create mode 100644 llvm/test/CodeGen/PowerPC/noredzone.ll diff --git a/llvm/test/CodeGen/PowerPC/noredzone.ll b/llvm/test/CodeGen/PowerPC/noredzone.ll new file mode 100644 index 0..3bd1e0867ba11 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/noredzone.ll @@ -0,0 +1,513 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-ibm-aix < %s | FileCheck -check-prefix=AIX64 +; RUN: llc -verify-machineinstrs -mtriple=powerpc-ibm-aix < %s | FileCheck -check-prefix=AIX32 +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu < %s | FileCheck -check-prefix=LE64 + +define signext i32 @leaf1_noredzone(i32 signext %a, i32 signext %b) #0 { +; AIX64-LABEL: leaf1_noredzone: +; AIX64: # %bb.0: # %entry +; AIX64-NEXT:stdu 1, -64(1) +; AIX64-NEXT:stw 3, 60(1) +; AIX64-NEXT:add 3, 3, 4 +; AIX64-NEXT:extsw 3, 3 +; AIX64-NEXT:stw 4, 56(1) +; AIX64-NEXT:addi 1, 1, 64 +; AIX64-NEXT:blr +; +; AIX32-LABEL: leaf1_noredzone: +; AIX32: # %bb.0: # %entry +; AIX32-NEXT:stwu 1, -32(1) +; AIX32-NEXT:stw 3, 28(1) +; AIX32-NEXT:add 3, 3, 4 +; AIX32-NEXT:stw 4, 24(1) +; AIX32-NEXT:addi 1, 1, 32 +; AIX32-NEXT:blr +; +; LE64-LABEL: leaf1_noredzone: +; LE64: # %bb.0: # %entry +; LE64-NEXT:stdu 1, -48(1) +; LE64-NEXT:stw 3, 44(1) +; LE64-NEXT:add 3, 3, 4 +; LE64-NEXT:stw 4, 40(1) +; LE64-NEXT:extsw 3, 3 +; LE64-NEXT:addi 1, 1, 48 +; LE64-NEXT:blr +entry: + %a.addr = alloca i32, align 4 + %b.addr = alloca i32, align 4 + store i32 %a, ptr %a.addr, align 4 + store i32 %b, ptr %b.addr, align 4 + %0 = load i32, ptr %a.addr, align 4 + %1 = load i32, ptr %b.addr, align 4 + %add = add nsw i32 %0, %1 + ret i32 %add +} + +define void @nonleaf1_noredzone(i32 signext %a, i32 signext %b) #0 { +; AIX64-LABEL: nonleaf1_noredzone: +; AIX64: # %bb.0: # %entry +; AIX64-NEXT:mflr 0 +; AIX64-NEXT:stdu 1, -128(1) +; AIX64-NEXT:std 0, 144(1) +; AIX64-NEXT:stw 3, 124(1) +; AIX64-NEXT:add 3, 3, 4 +; AIX64-NEXT:extsw 3, 3 +; AIX64-NEXT:stw 4, 120(1) +; AIX64-NEXT:bl .leaf2[PR] +; AIX64-NEXT:nop +; AIX64-NEXT:lwz 3, 124(1) +; AIX64-NEXT:lwz 4, 120(1) +; AIX64-NEXT:sub 3, 3, 4 +; AIX64-NEXT:extsw 3, 3 +; AIX64-NEXT:bl .leaf2[PR] +; AIX64-NEXT:nop +; AIX64-NEXT:addi 1, 1, 128 +; AIX64-NEXT:ld 0, 16(1) +; AIX64-NEXT:mtlr 0 +; AIX64-NEXT:blr +; +; AIX32-LABEL: nonleaf1_noredzone: +; AIX32: # %bb.0: # %entry +; AIX32-NEXT:mflr 0 +; AIX32-NEXT:stwu 1, -64(1) +; AIX32-NEXT:stw 0, 72(1) +; AIX32-NEXT:stw 3, 60(1) +; AIX32-NEXT:add 3, 3, 4 +; AIX32-NEXT:stw 4, 56(1) +; AIX32-NEXT:bl .leaf2[PR] +; AIX32-NEXT:nop +; AIX32-NEXT:lwz 3, 60(1) +; AIX32-NEXT:lwz 4, 56(1) +; AIX32-NEXT:sub 3, 3, 4 +; AIX32-NEXT:bl .leaf2[PR] +; AIX32-NEXT:nop +; AIX32-NEXT:addi 1, 1, 64 +; AIX32-NEXT:lwz 0, 8(1) +; AIX32-NEXT:mtlr 0 +; AIX32-NEXT:blr +; +; LE64-LABEL: nonleaf1_noredzone: +; LE64: # %bb.0: # %entry +; LE64-NEXT:mflr 0 +;