753 changes: 753 additions & 0 deletions bolt/test/X86/Inputs/dwarf5-df-input-lowpc-ranges-other.s

Large diffs are not rendered by default.

87 changes: 87 additions & 0 deletions bolt/test/X86/dwarf5-df-input-lowpc-ranges-cus.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
; RUN: rm -rf %t
; RUN: mkdir %t
; RUN: cd %t
; RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-df-input-lowpc-ranges-main.s \
; RUN: -split-dwarf-file=main.dwo -o main.o
; RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-df-input-lowpc-ranges-other.s \
; RUN: -split-dwarf-file=mainOther.dwo -o other.o
; RUN: %clang %cflags main.o other.o -o main.exe
; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections
; RUN: llvm-dwarfdump --show-form --verbose --debug-rnglists main.exe.bolt &> %t/foo.txt
; RUN: llvm-dwarfdump --show-form --verbose --debug-addr main.exe.bolt >> %t/foo.txt
; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.exe.bolt >> %t/foo.txt
; RUN: cat %t/foo.txt | FileCheck -check-prefix=BOLT %s
; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.dwo.dwo mainOther.dwo.dwo &> %t/mainddwodwo.txt
; RUN: cat %t/mainddwodwo.txt | FileCheck -check-prefix=BOLT-DWO-MAIN %s

;; Tests that BOLT correctly handles Skeleton CU which has DW_AT_low_pc/DW_AT_ranges as input and handles multiple CUs with ranges.

; BOLT: Addrs: [
; BOLT-NEXT: 0x[[#%.16x,ADDR1:]]
; BOLT-NEXT: 0x[[#%.16x,ADDR2:]]
; BOLT-NEXT: 0x[[#%.16x,ADDR3:]]
; BOLT-NEXT: 0x[[#%.16x,ADDR4:]]
; BOLT-NEXT: 0x[[#%.16x,ADDR5:]]

; BOLT: Addrs: [
; BOLT-NEXT: 0x[[#%.16x,ADDR6:]]
; BOLT-NEXT: 0x[[#%.16x,ADDR7:]]
; BOLT-NEXT: 0x[[#%.16x,ADDR8:]]
; BOLT-NEXT: 0x[[#%.16x,ADDR9:]]
; BOLT-NEXT: 0x[[#%.16x,ADDR10:]]

; BOLT: DW_TAG_skeleton_unit
; BOLT: DW_AT_dwo_name [DW_FORM_strx1] (indexed (00000001) string = "main.dwo.dwo")
; BOLT-NEXT: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
; BOLT-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x0) rangelist = 0x00000010
; BOLT-NEXT: [0x[[#ADDR1]], 0x[[#ADDR1 + 0x16]])
; BOLT-NEXT: [0x[[#ADDR1 + 0x16]], 0x[[#ADDR1 + 0x24]])
; BOLT-NEXT: [0x[[#ADDR1 + 0x24]], 0x[[#ADDR1 + 0x29]])
; BOLT-NEXT: [0x[[#ADDR1 + 0x30]], 0x[[#ADDR1 + 0x46]])
; BOLT-NEXT: [0x[[#ADDR1 + 0x50]], 0x[[#ADDR1 + 0x77]])
; BOLT-NEXT: [0x[[#ADDR1 + 0x77]], 0x[[#ADDR1 + 0x85]])
; BOLT-NEXT: [0x[[#ADDR1 + 0x85]], 0x[[#ADDR1 + 0x9f]])
; BOLT-NEXT: DW_AT_addr_base [DW_FORM_sec_offset] (0x00000008)
; BOLT-NEXT: DW_AT_rnglists_base [DW_FORM_sec_offset] (0x0000000c)

; BOLT: DW_TAG_skeleton_unit
; BOLT: DW_AT_dwo_name [DW_FORM_strx1] (indexed (00000001) string = "mainOther.dwo.dwo")
; BOLT-NEXT: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
; BOLT-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x0) rangelist = 0x0000003b
; BOLT-NEXT: [0x[[#ADDR6]], 0x[[#ADDR6 + 0x16]])
; BOLT-NEXT: [0x[[#ADDR6 + 0x16]], 0x[[#ADDR6 + 0x24]])
; BOLT-NEXT: [0x[[#ADDR6 + 0x24]], 0x[[#ADDR6 + 0x29]])
; BOLT-NEXT: [0x[[#ADDR6 + 0x30]], 0x[[#ADDR6 + 0x46]])
; BOLT-NEXT: [0x[[#ADDR6 + 0x50]], 0x[[#ADDR6 + 0x70]])
; BOLT-NEXT: [0x[[#ADDR6 + 0x70]], 0x[[#ADDR6 + 0x7e]])
; BOLT-NEXT: [0x[[#ADDR6 + 0x7e]], 0x[[#ADDR6 + 0x98]])
; BOLT-NEXT: DW_AT_addr_base [DW_FORM_sec_offset] (0x00000038)
; BOLT-NEXT: DW_AT_rnglists_base [DW_FORM_sec_offset] (0x00000037)

; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x0) rangelist = 0x00000014
; BOLT-DWO-MAIN-NEXT: [0x0000000000000000, 0x0000000000000016)
; BOLT-DWO-MAIN-NEXT: [0x0000000000000016, 0x0000000000000024)
; BOLT-DWO-MAIN-NEXT: [0x0000000000000024, 0x0000000000000029))
; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x1) rangelist = 0x00000020
; BOLT-DWO-MAIN-NEXT: [0x0000000000000002, 0x0000000000000029)
; BOLT-DWO-MAIN-NEXT: [0x0000000000000029, 0x0000000000000037)
; BOLT-DWO-MAIN-NEXT: [0x0000000000000037, 0x0000000000000051))

; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x0) rangelist = 0x00000014
; BOLT-DWO-MAIN-NEXT: [0x0000000000000000, 0x0000000000000016)
; BOLT-DWO-MAIN-NEXT: [0x0000000000000016, 0x0000000000000024)
; BOLT-DWO-MAIN-NEXT: [0x0000000000000024, 0x0000000000000029))
; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN: DW_TAG_subprogram
; BOLT-DWO-MAIN-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x1) rangelist = 0x00000020
; BOLT-DWO-MAIN-NEXT: [0x0000000000000002, 0x0000000000000022)
; BOLT-DWO-MAIN-NEXT: [0x0000000000000022, 0x0000000000000030)
; BOLT-DWO-MAIN-NEXT: [0x0000000000000030, 0x000000000000004a))
1 change: 1 addition & 0 deletions bolt/test/lsda-section-name.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// This test check that LSDA section named by .gcc_except_table.main is
// disassembled by BOLT.

// RUN: %clang++ %cxxflags -O3 -no-pie -c %s -o %t.o
// RUN: %clang++ %cxxflags -O3 -no-pie -fuse-ld=lld %t.o -o %t
// RUN: llvm-objcopy --rename-section .gcc_except_table=.gcc_except_table.main %t
// RUN: llvm-readelf -SW %t | FileCheck %s
Expand Down
21 changes: 11 additions & 10 deletions clang/cmake/caches/CrossWinToARMLinux.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,21 @@
# on Windows platform.
#
# NOTE: the build requires a development ARM Linux root filesystem to use
# proper target platform depended library and header files.
# proper target platform depended library and header files:
# - create <full-path-to-clang-configs> directory and put the clang configuration
# file named <TOOLCHAIN_TARGET_TRIPLE>.cfg into it.
# - add the `--sysroot=<path-to-develop-arm-linux-root-fs>` argument into
# this configuration file.
# - add other necessary target depended clang arguments there,
# such as '-mcpu=cortex-a78' & etc.
#
# See more details here: https://clang.llvm.org/docs/UsersManual.html#configuration-files
#
# Configure:
# cmake -G Ninja ^
# -DTOOLCHAIN_TARGET_TRIPLE=armv7-unknown-linux-gnueabihf ^
# -DTOOLCHAIN_TARGET_TRIPLE=aarch64-unknown-linux-gnu ^
# -DCMAKE_INSTALL_PREFIX=../install ^
# -DDEFAULT_SYSROOT=<path-to-develop-arm-linux-root-fs> ^
# -DLLVM_AR=<llvm_obj_root>/bin/llvm-ar[.exe] ^
# -DCLANG_CONFIG_FILE_USER_DIR=<full-path-to-clang-configs> ^
# -DCMAKE_CXX_FLAGS="-D__OPTIMIZE__" ^
# -DREMOTE_TEST_HOST="<hostname>" ^
# -DREMOTE_TEST_USER="<ssh_user_name>" ^
Expand Down Expand Up @@ -43,10 +50,6 @@ get_filename_component(LLVM_PROJECT_DIR
"${CMAKE_CURRENT_LIST_DIR}/../../../"
ABSOLUTE)

if (NOT DEFINED DEFAULT_SYSROOT)
message(WARNING "DEFAULT_SYSROOT must be specified for the cross toolchain build.")
endif()

if (NOT DEFINED LLVM_ENABLE_ASSERTIONS)
set(LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "")
endif()
Expand Down Expand Up @@ -136,7 +139,6 @@ endif()
set(LLVM_BUILTIN_TARGETS "${TOOLCHAIN_TARGET_TRIPLE}" CACHE STRING "")

set(BUILTINS_${TOOLCHAIN_TARGET_TRIPLE}_CMAKE_SYSTEM_NAME "Linux" CACHE STRING "")
set(BUILTINS_${TOOLCHAIN_TARGET_TRIPLE}_CMAKE_SYSROOT "${DEFAULT_SYSROOT}" CACHE STRING "")
set(BUILTINS_${TOOLCHAIN_TARGET_TRIPLE}_CMAKE_INSTALL_RPATH "${RUNTIMES_INSTALL_RPATH}" CACHE STRING "")
set(BUILTINS_${TOOLCHAIN_TARGET_TRIPLE}_CMAKE_BUILD_WITH_INSTALL_RPATH ON CACHE BOOL "")
set(BUILTINS_${TOOLCHAIN_TARGET_TRIPLE}_LLVM_CMAKE_DIR "${LLVM_PROJECT_DIR}/llvm/cmake/modules" CACHE PATH "")
Expand All @@ -156,7 +158,6 @@ set(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR ON CACHE BOOL "")
set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LLVM_ENABLE_RUNTIMES "${LLVM_ENABLE_RUNTIMES}" CACHE STRING "")

set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_CMAKE_SYSTEM_NAME "Linux" CACHE STRING "")
set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_CMAKE_SYSROOT "${DEFAULT_SYSROOT}" CACHE STRING "")
set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_CMAKE_INSTALL_RPATH "${RUNTIMES_INSTALL_RPATH}" CACHE STRING "")
set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_CMAKE_BUILD_WITH_INSTALL_RPATH ON CACHE BOOL "")

Expand Down
16 changes: 16 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@ C++23 Feature Support
- Implemented `P1774R8: Portable assumptions <https://wg21.link/P1774R8>`_.

- Implemented `P2448R2: Relaxing some constexpr restrictions <https://wg21.link/P2448R2>`_.
Note, the ``-Winvalid-constexpr`` diagnostic is now disabled in C++23 mode,
but can be explicitly specified to retain the old diagnostic checking
behavior.

- Added a ``__reference_converts_from_temporary`` builtin, completing the necessary compiler support for
`P2255R2: Type trait to determine if a reference binds to a temporary <https://wg21.link/P2255R2>`_.
Expand Down Expand Up @@ -323,6 +326,17 @@ Non-comprehensive list of changes in this release
- Builtins ``__builtin_shufflevector()`` and ``__builtin_convertvector()`` may
now be used within constant expressions.

- When compiling a constexpr function, Clang will check to see whether the
function can *never* be used in a constant expression context and issues a
diagnostic under the ``-Winvalid-constexpr`` diagostic flag (which defaults
to an error). This check can be expensive because the mere presence of a
function marked ``constexpr`` will cause us to undergo constant expression
evaluation, even if the function is not called within the translation unit
being compiled. Due to the expense, Clang no longer checks constexpr function
bodies when the function is defined in a system header file or when
``-Winvalid-constexpr`` is not enabled for the function definition, which
should result in mild compile-time performance improvements.

New Compiler Flags
------------------
- ``-fsanitize=implicit-bitfield-conversion`` checks implicit truncation and
Expand Down Expand Up @@ -824,6 +838,8 @@ Bug Fixes to C++ Support
- Fix a crash when a variable is captured by a block nested inside a lambda. (Fixes #GH93625).
- Fixed a type constraint substitution issue involving a generic lambda expression. (#GH93821)
- Fix a crash caused by improper use of ``__array_extent``. (#GH80474)
- Fixed several bugs in capturing variables within unevaluated contexts. (#GH63845), (#GH67260), (#GH69307),
(#GH88081), (#GH89496), (#GH90669) and (#GH91633).

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
70 changes: 35 additions & 35 deletions clang/docs/analyzer/checkers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1179,6 +1179,41 @@ security.insecureAPI.DeprecatedOrUnsafeBufferHandling (C)
strncpy(buf, "a", 1); // warn
}
.. _security-putenv-stack-array:
security.PutenvStackArray (C)
"""""""""""""""""""""""""""""
Finds calls to the ``putenv`` function which pass a pointer to a stack-allocated
(automatic) array as the argument. Function ``putenv`` does not copy the passed
string, only a pointer to the data is stored and this data can be read even by
other threads. Content of a stack-allocated array is likely to be overwritten
after exiting from the function.
The problem can be solved by using a static array variable or dynamically
allocated memory. Even better is to avoid using ``putenv`` (it has other
problems related to memory leaks) and use ``setenv`` instead.
The check corresponds to CERT rule
`POS34-C. Do not call putenv() with a pointer to an automatic variable as the argument
<https://wiki.sei.cmu.edu/confluence/display/c/POS34-C.+Do+not+call+putenv%28%29+with+a+pointer+to+an+automatic+variable+as+the+argument>`_.
.. code-block:: c
int f() {
char env[] = "NAME=value";
return putenv(env); // putenv function should not be called with stack-allocated string
}
There is one case where the checker can report a false positive. This is when
the stack-allocated array is used at `putenv` in a function or code branch that
does not return (process is terminated on all execution paths).
Another special case is if the `putenv` is called from function `main`. Here
the stack is deallocated at the end of the program and it should be no problem
to use the stack-allocated string (a multi-threaded program may require more
attention). The checker does not warn for cases when stack space of `main` is
used at the `putenv` call.
security.SetgidSetuidOrder (C)
""""""""""""""""""""""""""""""
When dropping user-level and group-level privileges in a program by using
Expand Down Expand Up @@ -2877,41 +2912,6 @@ Warn on mmap() calls that are both writable and executable.
// code
}
.. _alpha-security-putenv-stack-array:
alpha.security.PutenvStackArray (C)
"""""""""""""""""""""""""""""""""""
Finds calls to the ``putenv`` function which pass a pointer to a stack-allocated
(automatic) array as the argument. Function ``putenv`` does not copy the passed
string, only a pointer to the data is stored and this data can be read even by
other threads. Content of a stack-allocated array is likely to be overwritten
after returning from the parent function.
The problem can be solved by using a static array variable or dynamically
allocated memory. Even better is to avoid using ``putenv`` (it has other
problems related to memory leaks) and use ``setenv`` instead.
The check corresponds to CERT rule
`POS34-C. Do not call putenv() with a pointer to an automatic variable as the argument
<https://wiki.sei.cmu.edu/confluence/display/c/POS34-C.+Do+not+call+putenv%28%29+with+a+pointer+to+an+automatic+variable+as+the+argument>`_.
.. code-block:: c
int f() {
char env[] = "NAME=value";
return putenv(env); // putenv function should not be called with stack-allocated string
}
There is one case where the checker can report a false positive. This is when
the stack-allocated array is used at `putenv` in a function or code branch that
does not return (calls `fork` or `exec` like function).
Another special case is if the `putenv` is called from function `main`. Here
the stack is deallocated at the end of the program and it should be no problem
to use the stack-allocated string (a multi-threaded program may require more
attention). The checker does not warn for cases when stack space of `main` is
used at the `putenv` call.
.. _alpha-security-ReturnPtrRange:
alpha.security.ReturnPtrRange (C)
Expand Down
11 changes: 11 additions & 0 deletions clang/include/clang/AST/DeclBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,13 @@ class alignas(8) Decl {
/// Whether this declaration comes from another module unit.
bool isInAnotherModuleUnit() const;

/// Whether the definition of the declaration should be emitted in external
/// sources.
bool shouldEmitInExternalSource() const;

/// Whether this declaration comes from a named module;
bool isInNamedModule() const;

/// Whether this declaration comes from explicit global module.
bool isFromExplicitGlobalModule() const;

Expand Down Expand Up @@ -2148,6 +2155,10 @@ class DeclContext {
getDeclKind() <= Decl::lastRecord;
}

bool isRequiresExprBody() const {
return getDeclKind() == Decl::RequiresExprBody;
}

bool isNamespace() const { return getDeclKind() == Decl::Namespace; }

bool isStdNamespace() const;
Expand Down
5 changes: 0 additions & 5 deletions clang/include/clang/AST/TemplateName.h
Original file line number Diff line number Diff line change
Expand Up @@ -314,11 +314,6 @@ class TemplateName {

TemplateName getUnderlying() const;

/// Get the template name to substitute when this template name is used as a
/// template template argument. This refers to the most recent declaration of
/// the template, including any default template arguments.
TemplateName getNameToSubstitute() const;

TemplateNameDependence getDependence() const;

/// Determines whether this is a dependent template name.
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -4500,6 +4500,7 @@ def HLSLShader : InheritableAttr {
case HLSLShaderAttr::Mesh: return llvm::Triple::Mesh;
case HLSLShaderAttr::Amplification: return llvm::Triple::Amplification;
}
llvm_unreachable("unknown enumeration value");
}
}];
}
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/CharInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ LLVM_READONLY inline bool isRawStringDelimBody(unsigned char c) {
using namespace charinfo;
return (InfoTable[c] & (CHAR_UPPER | CHAR_LOWER | CHAR_PERIOD | CHAR_DIGIT |
CHAR_UNDER | CHAR_PUNCT)) != 0 &&
c != '(' && c != ')';
c != '(' && c != ')' && c != '\\';
}

enum class EscapeChar {
Expand Down
8 changes: 8 additions & 0 deletions clang/include/clang/Basic/LangOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,14 @@ COMPATIBLE_LANGOPT(IncrementalExtensions, 1, 0, " True if we want to process sta

BENIGN_LANGOPT(CheckNew, 1, 0, "Do not assume C++ operator new may not return NULL")

// FIXME: It would be better for us to find a way to encode the state of this
// diagnostic in tablegen so that we can specify a particular diagnostic option
// is disabled or enabled based on other language options or made it easier to
// do this from the compiler invocation without hitting option round-tripping
// issues.
BENIGN_LANGOPT(CheckConstexprFunctionBodies, 1, 1,
"Emit diagnostics for a constexpr function body that can never "
"be used in a constant expression.")
#undef LANGOPT
#undef COMPATIBLE_LANGOPT
#undef BENIGN_LANGOPT
Expand Down
18 changes: 18 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,17 @@ multiclass BoolMOption<string flag_base, KeyPathAndMacro kpm,
Group<m_Group>;
}

/// Creates a BoolOption where both of the flags are prefixed with "W", are in
/// the Group<W_Group>.
/// Used for -cc1 frontend options. Driver-only options do not map to
/// CompilerInvocation.
multiclass BoolWOption<string flag_base, KeyPathAndMacro kpm,
Default default, FlagDef flag1, FlagDef flag2,
BothFlags both = BothFlags<[]>> {
defm NAME : BoolOption<"W", flag_base, kpm, default, flag1, flag2, both>,
Group<W_Group>;
}

// Works like BoolOption except without marshalling
multiclass BoolOptionWithoutMarshalling<string prefix = "", string spelling_base,
FlagDef flag1_base, FlagDef flag2_base,
Expand Down Expand Up @@ -606,6 +617,7 @@ defvar cpp11 = LangOpts<"CPlusPlus11">;
defvar cpp14 = LangOpts<"CPlusPlus14">;
defvar cpp17 = LangOpts<"CPlusPlus17">;
defvar cpp20 = LangOpts<"CPlusPlus20">;
defvar cpp23 = LangOpts<"CPlusPlus23">;
defvar c99 = LangOpts<"C99">;
defvar c23 = LangOpts<"C23">;
defvar lang_std = LangOpts<"LangStd">;
Expand Down Expand Up @@ -961,6 +973,12 @@ def Wdeprecated : Flag<["-"], "Wdeprecated">, Group<W_Group>,
HelpText<"Enable warnings for deprecated constructs and define __DEPRECATED">;
def Wno_deprecated : Flag<["-"], "Wno-deprecated">, Group<W_Group>,
Visibility<[ClangOption, CC1Option]>;
defm invalid_constexpr : BoolWOption<"invalid-constexpr",
LangOpts<"CheckConstexprFunctionBodies">,
Default<!strconcat("!", cpp23.KeyPath)>,
NegFlag<SetFalse, [], [ClangOption, CC1Option], "Disable">,
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Enable">,
BothFlags<[], [ClangOption, CC1Option], " checking of constexpr function bodies for validity within a constant expression context">>;
def Wl_COMMA : CommaJoined<["-"], "Wl,">, Visibility<[ClangOption, FlangOption]>,
Flags<[LinkerInput, RenderAsInput]>,
HelpText<"Pass the comma separated arguments in <arg> to the linker">,
Expand Down
10 changes: 5 additions & 5 deletions clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
Original file line number Diff line number Diff line change
Expand Up @@ -1011,6 +1011,11 @@ def FloatLoopCounter : Checker<"FloatLoopCounter">,
Dependencies<[SecuritySyntaxChecker]>,
Documentation<HasDocumentation>;

def PutenvStackArray : Checker<"PutenvStackArray">,
HelpText<"Finds calls to the function 'putenv' which pass a pointer to "
"an automatic (stack-allocated) array as the argument.">,
Documentation<HasDocumentation>;

def SetgidSetuidOrderChecker : Checker<"SetgidSetuidOrder">,
HelpText<"Warn on possible reversed order of 'setgid(getgid()))' and "
"'setuid(getuid())' (CERT: POS36-C)">,
Expand Down Expand Up @@ -1065,11 +1070,6 @@ def MmapWriteExecChecker : Checker<"MmapWriteExec">,
]>,
Documentation<HasDocumentation>;

def PutenvStackArray : Checker<"PutenvStackArray">,
HelpText<"Finds calls to the function 'putenv' which pass a pointer to "
"an automatic (stack-allocated) array as the argument.">,
Documentation<HasDocumentation>;

def ReturnPointerRangeChecker : Checker<"ReturnPtrRange">,
HelpText<"Check for an out-of-bound pointer being returned to callers">,
Documentation<HasDocumentation>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_MODULEDEPCOLLECTOR_H

#include "clang/Basic/LLVM.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/Utils.h"
Expand Down Expand Up @@ -138,6 +139,10 @@ struct ModuleDeps {
/// determined that the differences are benign for this compilation.
std::vector<ModuleID> ClangModuleDeps;

/// The set of libraries or frameworks to link against when
/// an entity from this module is used.
llvm::SmallVector<Module::LinkLibrary, 2> LinkLibraries;

/// Get (or compute) the compiler invocation that can be used to build this
/// module. Does not include argv[0].
const std::vector<std::string> &getBuildArguments();
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12018,7 +12018,7 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
return false;

// Variables in other module units shouldn't be forced to be emitted.
if (VD->isInAnotherModuleUnit())
if (VD->shouldEmitInExternalSource())
return false;

// Variables that can be needed in other TUs are required.
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/ASTImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2929,7 +2929,7 @@ ExpectedDecl ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {

// We may already have an enum of the same name; try to find and match it.
EnumDecl *PrevDecl = nullptr;
if (!DC->isFunctionOrMethod() && SearchName) {
if (!DC->isFunctionOrMethod()) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
auto FoundDecls =
Importer.findDeclsInToCtx(DC, SearchName);
Expand Down
11 changes: 2 additions & 9 deletions clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1174,13 +1174,6 @@ Linkage NamedDecl::getLinkageInternal() const {
.getLinkage();
}

/// Determine whether D is attached to a named module.
static bool isInNamedModule(const NamedDecl *D) {
if (auto *M = D->getOwningModule())
return M->isNamedModule();
return false;
}

static bool isExportedFromModuleInterfaceUnit(const NamedDecl *D) {
// FIXME: Handle isModulePrivate.
switch (D->getModuleOwnershipKind()) {
Expand All @@ -1190,7 +1183,7 @@ static bool isExportedFromModuleInterfaceUnit(const NamedDecl *D) {
return false;
case Decl::ModuleOwnershipKind::Visible:
case Decl::ModuleOwnershipKind::VisibleWhenImported:
return isInNamedModule(D);
return D->isInNamedModule();
}
llvm_unreachable("unexpected module ownership kind");
}
Expand All @@ -1208,7 +1201,7 @@ Linkage NamedDecl::getFormalLinkage() const {
// [basic.namespace.general]/p2
// A namespace is never attached to a named module and never has a name with
// module linkage.
if (isInNamedModule(this) && InternalLinkage == Linkage::External &&
if (isInNamedModule() && InternalLinkage == Linkage::External &&
!isExportedFromModuleInterfaceUnit(
cast<NamedDecl>(this->getCanonicalDecl())) &&
!isa<NamespaceDecl>(this))
Expand Down
23 changes: 11 additions & 12 deletions clang/lib/AST/DeclBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1100,23 +1100,22 @@ bool Decl::isInExportDeclContext() const {
bool Decl::isInAnotherModuleUnit() const {
auto *M = getOwningModule();

if (!M)
if (!M || !M->isNamedModule())
return false;

M = M->getTopLevelModule();
// FIXME: It is problematic if the header module lives in another module
// unit. Consider to fix this by techniques like
// ExternalASTSource::hasExternalDefinitions.
if (M->isHeaderLikeModule())
return false;
return M != getASTContext().getCurrentNamedModule();
}

// A global module without parent implies that we're parsing the global
// module. So it can't be in another module unit.
if (M->isGlobalModule())
bool Decl::shouldEmitInExternalSource() const {
ExternalASTSource *Source = getASTContext().getExternalSource();
if (!Source)
return false;

assert(M->isNamedModule() && "New module kind?");
return M != getASTContext().getCurrentNamedModule();
return Source->hasExternalDefinitions(this) == ExternalASTSource::EK_Always;
}

bool Decl::isInNamedModule() const {
return getOwningModule() && getOwningModule()->isNamedModule();
}

bool Decl::isFromExplicitGlobalModule() const {
Expand Down
4 changes: 1 addition & 3 deletions clang/lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3618,12 +3618,10 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case ConceptSpecializationExprClass:
case RequiresExprClass:
case SYCLUniqueStableNameExprClass:
case PackIndexingExprClass:
// These never have a side-effect.
return false;

case PackIndexingExprClass:
return cast<PackIndexingExpr>(this)->getSelectedExpr()->HasSideEffects(
Ctx, IncludePossibleEffects);
case ConstantExprClass:
// FIXME: Move this into the "return false;" block above.
return cast<ConstantExpr>(this)->getSubExpr()->HasSideEffects(
Expand Down
17 changes: 0 additions & 17 deletions clang/lib/AST/TemplateName.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,23 +214,6 @@ UsingShadowDecl *TemplateName::getAsUsingShadowDecl() const {
return nullptr;
}

TemplateName TemplateName::getNameToSubstitute() const {
TemplateDecl *Decl = getAsTemplateDecl();

// Substituting a dependent template name: preserve it as written.
if (!Decl)
return *this;

// If we have a template declaration, use the most recent non-friend
// declaration of that template.
Decl = cast<TemplateDecl>(Decl->getMostRecentDecl());
while (Decl->getFriendObjectKind()) {
Decl = cast<TemplateDecl>(Decl->getPreviousDecl());
assert(Decl && "all declarations of template are friends");
}
return TemplateName(Decl);
}

TemplateNameDependence TemplateName::getDependence() const {
auto D = TemplateNameDependence::None;
switch (getKind()) {
Expand Down
21 changes: 21 additions & 0 deletions clang/lib/Analysis/FlowSensitive/Transfer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,13 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
const Expr *RHS = S->getRHS();
assert(RHS != nullptr);

// Do compound assignments up-front, as there are so many of them and we
// don't want to list all of them in the switch statement below.
// To avoid generating unnecessary values, we don't create a new value but
// instead leave it to the specific analysis to do this if desired.
if (S->isCompoundAssignmentOp())
propagateStorageLocation(*S->getLHS(), *S, Env);

switch (S->getOpcode()) {
case BO_Assign: {
auto *LHSLoc = Env.getStorageLocation(*LHS);
Expand Down Expand Up @@ -382,6 +389,20 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
Env.setValue(*S, Env.makeNot(*SubExprVal));
break;
}
case UO_PreInc:
case UO_PreDec:
// Propagate the storage location, but don't create a new value; to
// avoid generating unnecessary values, we leave it to the specific
// analysis to do this if desired.
propagateStorageLocation(*S->getSubExpr(), *S, Env);
break;
case UO_PostInc:
case UO_PostDec:
// Propagate the old value, but don't create a new value; to avoid
// generating unnecessary values, we leave it to the specific analysis
// to do this if desired.
propagateValue(*S->getSubExpr(), *S, Env);
break;
default:
break;
}
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGVTables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1200,7 +1200,7 @@ bool CodeGenVTables::isVTableExternal(const CXXRecordDecl *RD) {
assert(Def && "The body of the key function is not assigned to Def?");
// If the non-inline key function comes from another module unit, the vtable
// must be defined there.
return Def->isInAnotherModuleUnit() && !Def->isInlineSpecified();
return Def->shouldEmitInExternalSource() && !Def->isInlineSpecified();
}

/// Given that we're currently at the end of the translation unit, and
Expand Down
19 changes: 16 additions & 3 deletions clang/lib/CodeGen/Targets/AMDGPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ class AMDGPUABIInfo final : public DefaultABIInfo {

ABIArgInfo classifyReturnType(QualType RetTy) const;
ABIArgInfo classifyKernelArgumentType(QualType Ty) const;
ABIArgInfo classifyArgumentType(QualType Ty, unsigned &NumRegsLeft) const;
ABIArgInfo classifyArgumentType(QualType Ty, bool Variadic,
unsigned &NumRegsLeft) const;

void computeInfo(CGFunctionInfo &FI) const override;
Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
Expand Down Expand Up @@ -103,12 +104,16 @@ void AMDGPUABIInfo::computeInfo(CGFunctionInfo &FI) const {
if (!getCXXABI().classifyReturnType(FI))
FI.getReturnInfo() = classifyReturnType(FI.getReturnType());

unsigned ArgumentIndex = 0;
const unsigned numFixedArguments = FI.getNumRequiredArgs();

unsigned NumRegsLeft = MaxNumRegsForArgsRet;
for (auto &Arg : FI.arguments()) {
if (CC == llvm::CallingConv::AMDGPU_KERNEL) {
Arg.info = classifyKernelArgumentType(Arg.type);
} else {
Arg.info = classifyArgumentType(Arg.type, NumRegsLeft);
bool FixedArgument = ArgumentIndex++ < numFixedArguments;
Arg.info = classifyArgumentType(Arg.type, !FixedArgument, NumRegsLeft);
}
}
}
Expand Down Expand Up @@ -197,12 +202,20 @@ ABIArgInfo AMDGPUABIInfo::classifyKernelArgumentType(QualType Ty) const {
return ABIArgInfo::getDirect(LTy, 0, nullptr, false);
}

ABIArgInfo AMDGPUABIInfo::classifyArgumentType(QualType Ty,
ABIArgInfo AMDGPUABIInfo::classifyArgumentType(QualType Ty, bool Variadic,
unsigned &NumRegsLeft) const {
assert(NumRegsLeft <= MaxNumRegsForArgsRet && "register estimate underflow");

Ty = useFirstFieldIfTransparentUnion(Ty);

if (Variadic) {
return ABIArgInfo::getDirect(/*T=*/nullptr,
/*Offset=*/0,
/*Padding=*/nullptr,
/*CanBeFlattened=*/false,
/*Align=*/0);
}

if (isAggregateTypeForABI(Ty)) {
// Records with non-trivial destructors/copy-constructors should not be
// passed by value.
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2407,6 +2407,9 @@ void CompilerInvocationBase::GenerateDiagnosticArgs(
// This option is automatically generated from UndefPrefixes.
if (Warning == "undef-prefix")
continue;
// This option is automatically generated from CheckConstexprFunctionBodies.
if (Warning == "invalid-constexpr" || Warning == "no-invalid-constexpr")
continue;
Consumer(StringRef("-W") + Warning);
}

Expand Down
13 changes: 11 additions & 2 deletions clang/lib/Interpreter/IncrementalParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -387,8 +387,7 @@ std::unique_ptr<llvm::Module> IncrementalParser::GenModule() {

void IncrementalParser::CleanUpPTU(PartialTranslationUnit &PTU) {
TranslationUnitDecl *MostRecentTU = PTU.TUPart;
TranslationUnitDecl *FirstTU = MostRecentTU->getFirstDecl();
if (StoredDeclsMap *Map = FirstTU->getPrimaryContext()->getLookupPtr()) {
if (StoredDeclsMap *Map = MostRecentTU->getPrimaryContext()->getLookupPtr()) {
for (auto &&[Key, List] : *Map) {
DeclContextLookupResult R = List.getLookupResult();
std::vector<NamedDecl *> NamedDeclsToRemove;
Expand All @@ -407,6 +406,16 @@ void IncrementalParser::CleanUpPTU(PartialTranslationUnit &PTU) {
}
}
}

// FIXME: We should de-allocate MostRecentTU
for (Decl *D : MostRecentTU->decls()) {
auto *ND = dyn_cast<NamedDecl>(D);
if (!ND)
continue;
// Check if we need to clean up the IdResolver chain.
if (ND->getDeclName().getFETokenInfo())
getCI()->getSema().IdResolver.RemoveDecl(ND);
}
}

llvm::StringRef IncrementalParser::GetMangledName(GlobalDecl GD) const {
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/Parse/ParseExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1581,7 +1581,10 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
TrailingReturnTypeLoc, &DS),
std::move(Attributes), DeclEndLoc);

Actions.ActOnLambdaClosureQualifiers(Intro, MutableLoc);
// We have called ActOnLambdaClosureQualifiers for parentheses-less cases
// above.
if (HasParentheses)
Actions.ActOnLambdaClosureQualifiers(Intro, MutableLoc);

if (HasParentheses && Tok.is(tok::kw_requires))
ParseTrailingRequiresClause(D);
Expand Down
12 changes: 8 additions & 4 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2284,9 +2284,13 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
if (LabelDecl *LD = dyn_cast<LabelDecl>(D))
CheckPoppedLabel(LD, *this, addDiag);

// Remove this name from our lexical scope, and warn on it if we haven't
// already.
IdResolver.RemoveDecl(D);
// Partial translation units that are created in incremental processing must
// not clean up the IdResolver because PTUs should take into account the
// declarations that came from previous PTUs.
if (!PP.isIncrementalProcessingEnabled() || getLangOpts().ObjC)
IdResolver.RemoveDecl(D);

// Warn on it if we are shadowing a declaration.
auto ShadowI = ShadowingDecls.find(D);
if (ShadowI != ShadowingDecls.end()) {
if (const auto *FD = dyn_cast<FieldDecl>(ShadowI->second)) {
Expand Down Expand Up @@ -10244,7 +10248,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// check at the end of the TU (or when the PMF starts) to see that we
// have a definition at that point.
if (isInline && !D.isFunctionDefinition() && getLangOpts().CPlusPlus20 &&
NewFD->hasOwningModule() && NewFD->getOwningModule()->isNamedModule()) {
NewFD->isInNamedModule()) {
PendingInlineFuncDecls.insert(NewFD);
}
}
Expand Down
15 changes: 11 additions & 4 deletions clang/lib/Sema/SemaDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2469,11 +2469,18 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl,
// base class sub-objects shall be a constexpr constructor.
//
// Note that this rule is distinct from the "requirements for a constexpr
// function", so is not checked in CheckValid mode.
// function", so is not checked in CheckValid mode. Because the check for
// constexpr potential is expensive, skip the check if the diagnostic is
// disabled, the function is declared in a system header, or we're in C++23
// or later mode (see https://wg21.link/P2448).
bool SkipCheck =
!SemaRef.getLangOpts().CheckConstexprFunctionBodies ||
SemaRef.getSourceManager().isInSystemHeader(Dcl->getLocation()) ||
SemaRef.getDiagnostics().isIgnored(
diag::ext_constexpr_function_never_constant_expr, Dcl->getLocation());
SmallVector<PartialDiagnosticAt, 8> Diags;
if (Kind == Sema::CheckConstexprKind::Diagnose &&
!Expr::isPotentialConstantExpr(Dcl, Diags) &&
!SemaRef.getLangOpts().CPlusPlus23) {
if (Kind == Sema::CheckConstexprKind::Diagnose && !SkipCheck &&
!Expr::isPotentialConstantExpr(Dcl, Diags)) {
SemaRef.Diag(Dcl->getLocation(),
diag::ext_constexpr_function_never_constant_expr)
<< isa<CXXConstructorDecl>(Dcl) << Dcl->isConsteval()
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18768,13 +18768,23 @@ bool Sema::tryCaptureVariable(
DeclContext *VarDC = Var->getDeclContext();
DeclContext *DC = CurContext;

// Skip past RequiresExprBodys because they don't constitute function scopes.
while (DC->isRequiresExprBody())
DC = DC->getParent();

// tryCaptureVariable is called every time a DeclRef is formed,
// it can therefore have non-negigible impact on performances.
// For local variables and when there is no capturing scope,
// we can bailout early.
if (CapturingFunctionScopes == 0 && (!BuildAndDiagnose || VarDC == DC))
return true;

// Exception: Function parameters are not tied to the function's DeclContext
// until we enter the function definition. Capturing them anyway would result
// in an out-of-bounds error while traversing DC and its parents.
if (isa<ParmVarDecl>(Var) && !VarDC->isFunctionOrMethod())
return true;

const auto *VD = dyn_cast<VarDecl>(Var);
if (VD) {
if (VD->isInitCapture())
Expand Down
23 changes: 10 additions & 13 deletions clang/lib/Sema/SemaInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -814,19 +814,13 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,

if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) {
const RecordDecl *RDecl = RType->getDecl();
if (RDecl->isUnion() && ILE->getInitializedFieldInUnion())
FillInEmptyInitForField(0, ILE->getInitializedFieldInUnion(),
Entity, ILE, RequiresSecondPass, FillWithNoInit);
else if (RDecl->isUnion() && isa<CXXRecordDecl>(RDecl) &&
cast<CXXRecordDecl>(RDecl)->hasInClassInitializer()) {
for (auto *Field : RDecl->fields()) {
if (Field->hasInClassInitializer()) {
FillInEmptyInitForField(0, Field, Entity, ILE, RequiresSecondPass,
FillWithNoInit);
break;
}
}
if (RDecl->isUnion() && ILE->getInitializedFieldInUnion()) {
FillInEmptyInitForField(0, ILE->getInitializedFieldInUnion(), Entity, ILE,
RequiresSecondPass, FillWithNoInit);
} else {
assert((!RDecl->isUnion() || !isa<CXXRecordDecl>(RDecl) ||
!cast<CXXRecordDecl>(RDecl)->hasInClassInitializer()) &&
"We should have computed initialized fields already");
// The fields beyond ILE->getNumInits() are default initialized, so in
// order to leave them uninitialized, the ILE is expanded and the extra
// fields are then filled with NoInitExpr.
Expand Down Expand Up @@ -2164,12 +2158,15 @@ void InitListChecker::CheckStructUnionTypes(
return;
for (RecordDecl::field_iterator FieldEnd = RD->field_end();
Field != FieldEnd; ++Field) {
if (Field->hasInClassInitializer()) {
if (Field->hasInClassInitializer() ||
(Field->isAnonymousStructOrUnion() &&
Field->getType()->getAsCXXRecordDecl()->hasInClassInitializer())) {
StructuredList->setInitializedFieldInUnion(*Field);
// FIXME: Actually build a CXXDefaultInitExpr?
return;
}
}
llvm_unreachable("Couldn't find in-class initializer");
}

// Value-initialize the first member of the union that isn't an unnamed
Expand Down
29 changes: 20 additions & 9 deletions clang/lib/Sema/SemaLambda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1076,16 +1076,27 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro,
// be dependent, because there are template parameters in scope.
CXXRecordDecl::LambdaDependencyKind LambdaDependencyKind =
CXXRecordDecl::LDK_Unknown;
if (LSI->NumExplicitTemplateParams > 0) {
Scope *TemplateParamScope = CurScope->getTemplateParamParent();
assert(TemplateParamScope &&
"Lambda with explicit template param list should establish a "
"template param scope");
assert(TemplateParamScope->getParent());
if (TemplateParamScope->getParent()->getTemplateParamParent() != nullptr)
LambdaDependencyKind = CXXRecordDecl::LDK_AlwaysDependent;
} else if (CurScope->getTemplateParamParent() != nullptr) {
if (CurScope->getTemplateParamParent() != nullptr) {
LambdaDependencyKind = CXXRecordDecl::LDK_AlwaysDependent;
} else if (Scope *P = CurScope->getParent()) {
// Given a lambda defined inside a requires expression,
//
// struct S {
// S(auto var) requires requires { [&] -> decltype(var) { }; }
// {}
// };
//
// The parameter var is not injected into the function Decl at the point of
// parsing lambda. In such scenarios, perceiving it as dependent could
// result in the constraint being evaluated, which matches what GCC does.
while (P->getEntity() && P->getEntity()->isRequiresExprBody())
P = P->getParent();
if (P->isFunctionDeclarationScope() &&
llvm::any_of(P->decls(), [](Decl *D) {
return isa<ParmVarDecl>(D) &&
cast<ParmVarDecl>(D)->getType()->isTemplateTypeParmType();
}))
LambdaDependencyKind = CXXRecordDecl::LDK_AlwaysDependent;
}

CXXRecordDecl *Class = createLambdaClosureType(
Expand Down
10 changes: 4 additions & 6 deletions clang/lib/Sema/SemaTemplateInstantiate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1856,7 +1856,7 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
}

TemplateName Template = Arg.getAsTemplate().getNameToSubstitute();
TemplateName Template = Arg.getAsTemplate();
assert(!Template.isNull() && Template.getAsTemplateDecl() &&
"Wrong kind of template template argument");
return Template.getAsTemplateDecl();
Expand Down Expand Up @@ -2029,10 +2029,8 @@ TemplateName TemplateInstantiator::TransformTemplateName(
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
}

TemplateName Template = Arg.getAsTemplate().getNameToSubstitute();
TemplateName Template = Arg.getAsTemplate();
assert(!Template.isNull() && "Null template template argument");
assert(!Template.getAsQualifiedTemplateName() &&
"template decl to substitute is qualified?");

if (Final)
return Template;
Expand All @@ -2052,8 +2050,8 @@ TemplateName TemplateInstantiator::TransformTemplateName(
if (SubstPack->getFinal())
return Template;
return getSema().Context.getSubstTemplateTemplateParm(
Template.getNameToSubstitute(), SubstPack->getAssociatedDecl(),
SubstPack->getIndex(), getPackIndex(Pack));
Template, SubstPack->getAssociatedDecl(), SubstPack->getIndex(),
getPackIndex(Pack));
}

return inherited::TransformTemplateName(SS, Name, NameLoc, ObjectType,
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/TreeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -14247,7 +14247,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
// will be deemed as dependent even if there are no dependent template
// arguments.
// (A ClassTemplateSpecializationDecl is always a dependent context.)
while (DC->getDeclKind() == Decl::Kind::RequiresExprBody)
while (DC->isRequiresExprBody())
DC = DC->getParent();
if ((getSema().isUnevaluatedContext() ||
getSema().isConstantEvaluatedContext()) &&
Expand Down
13 changes: 7 additions & 6 deletions clang/lib/Serialization/ASTWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3897,8 +3897,7 @@ void ASTWriter::WriteIdentifierTable(Preprocessor &PP,

// Write out identifiers if either the ID is local or the identifier has
// changed since it was loaded.
if (ID >= FirstIdentID || !Chain || !II->isFromAST() ||
II->hasChangedSinceDeserialization() ||
if (ID >= FirstIdentID || II->hasChangedSinceDeserialization() ||
(Trait.needDecls() &&
II->hasFETokenInfoChangedSinceDeserialization()))
Generator.insert(II, ID, Trait);
Expand Down Expand Up @@ -6509,10 +6508,12 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) {
// computed.
Record->push_back(D->getODRHash());

bool ModulesDebugInfo =
Writer->Context->getLangOpts().ModulesDebugInfo && !D->isDependentType();
Record->push_back(ModulesDebugInfo);
if (ModulesDebugInfo)
bool ModulesCodegen =
!D->isDependentType() &&
(Writer->Context->getLangOpts().ModulesDebugInfo ||
D->isInNamedModule());
Record->push_back(ModulesCodegen);
if (ModulesCodegen)
Writer->AddDeclRef(D, Writer->ModularCodegenDecls);

// IsLambda bit is already saved.
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,10 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {

MD.ID.ModuleName = M->getFullModuleName();
MD.IsSystem = M->IsSystem;
// For modules which use export_as link name, the linked product that of the
// corresponding export_as-named module.
if (!M->UseExportAsModuleLinkName)
MD.LinkLibraries = M->LinkLibraries;

ModuleMap &ModMapInfo =
MDC.ScanInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap();
Expand Down
2 changes: 1 addition & 1 deletion clang/test/AST/ast-dump-APValue-anon-union.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ void Test() {

constexpr U0 u0a{};
// CHECK: | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u0a 'const U0' constexpr listinit
// CHECK-NEXT: | |-value: Union None
// CHECK-NEXT: | |-value: Union .U0::(anonymous union at {{.*}}) Union .f Float 3.141500e+00

constexpr U0 u0b{3.1415f};
// CHECK: | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u0b 'const U0' constexpr listinit
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Analysis/putenv-stack-array.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// RUN: %clang_analyze_cc1 \
// RUN: -analyzer-checker=alpha.security.PutenvStackArray \
// RUN: -analyzer-checker=security.PutenvStackArray \
// RUN: -verify %s

#include "Inputs/system-header-simulator.h"
Expand Down
92 changes: 92 additions & 0 deletions clang/test/CXX/drs/cwg18xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,98 @@ namespace cwg1837 { // cwg1837: 3.3
#endif
}

namespace cwg1862 { // cwg1862: no
template<class T>
struct A {
struct B {
void e();
};

void f();

struct D {
void g();
};

T h();

template<T U>
T i();
};

template<>
struct A<int> {
struct B {
void e();
};

int f();

struct D {
void g();
};

template<int U>
int i();
};

template<>
struct A<float*> {
int* h();
};

class C {
int private_int;

template<class T>
friend struct A<T>::B;
// expected-warning@-1 {{dependent nested name specifier 'A<T>::' for friend class declaration is not supported; turning off access control for 'C'}}

template<class T>
friend void A<T>::f();
// expected-warning@-1 {{dependent nested name specifier 'A<T>::' for friend class declaration is not supported; turning off access control for 'C'}}

// FIXME: this is ill-formed, because A<T>​::​D does not end with a simple-template-id
template<class T>
friend void A<T>::D::g();
// expected-warning@-1 {{dependent nested name specifier 'A<T>::D::' for friend class declaration is not supported; turning off access control for 'C'}}

template<class T>
friend int *A<T*>::h();
// expected-warning@-1 {{dependent nested name specifier 'A<T *>::' for friend class declaration is not supported; turning off access control for 'C'}}

template<class T>
template<T U>
friend T A<T>::i();
// expected-warning@-1 {{dependent nested name specifier 'A<T>::' for friend class declaration is not supported; turning off access control for 'C'}}
};

C c;

template<class T>
void A<T>::B::e() { (void)c.private_int; }
void A<int>::B::e() { (void)c.private_int; }

template<class T>
void A<T>::f() { (void)c.private_int; }
int A<int>::f() { (void)c.private_int; return 0; }

// FIXME: both definition of 'D::g' are not friends, so they don't have access to 'private_int'
template<class T>
void A<T>::D::g() { (void)c.private_int; }
void A<int>::D::g() { (void)c.private_int; }

template<class T>
T A<T>::h() { (void)c.private_int; }
int* A<float*>::h() { (void)c.private_int; return 0; }

template<class T>
template<T U>
T A<T>::i() { (void)c.private_int; }
template<int U>
int A<int>::i() { (void)c.private_int; }
} // namespace cwg1862

namespace cwg1872 { // cwg1872: 9
#if __cplusplus >= 201103L
template<typename T> struct A : T {
Expand Down
39 changes: 39 additions & 0 deletions clang/test/CXX/drs/cwg19xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,30 @@ namespace cwg1909 { // cwg1909: 3.7
};
}

namespace cwg1918 { // cwg1918: no
template<typename T> struct A {
class B {
class C {};
};
};
class X {
static int x;
// FIXME: this is ill-formed, because A<T>::B::C does not end with a simple-template-id
template <typename T>
friend class A<T>::B::C;
// expected-warning@-1 {{dependent nested name specifier 'A<T>::B::' for friend class declaration is not supported; turning off access control for 'X'}}
};
template<> struct A<int> {
typedef struct Q B;
};
struct Q {
class C {
// FIXME: 'f' is not a friend, so 'X::x' is not accessible
int f() { return X::x; }
};
};
} // namespace cwg1918

namespace cwg1940 { // cwg1940: 3.5
#if __cplusplus >= 201103L
static union {
Expand Down Expand Up @@ -121,6 +145,21 @@ derived d2(42, 9);
#endif
}

namespace cwg1945 { // cwg1945: no
template<typename T> struct A {
class B {
class C {};
};
};
class X {
static int x;
// FIXME: this is ill-formed, because A<T>::B::C does not end with a simple-template-id
template <typename T>
friend class A<T>::B::C;
// expected-warning@-1 {{dependent nested name specifier 'A<T>::B::' for friend class declaration is not supported; turning off access control for 'X'}}
};
} // namespace cwg1945

namespace cwg1947 { // cwg1947: 3.5
#if __cplusplus >= 201402L
unsigned o = 0'01; // ok
Expand Down
47 changes: 0 additions & 47 deletions clang/test/CXX/drs/cwg2390.cpp

This file was deleted.

37 changes: 36 additions & 1 deletion clang/test/CXX/drs/cwg23xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,42 @@ namespace cwg2387 { // cwg2387: 9
#endif
}

// cwg2390 is in cwg2390.cpp
namespace cwg2390 { // cwg2390: 14
// Test that macro expansion of the builtin argument works.
#define C clang
#define F fallthrough
#define CF clang::fallthrough

#if !__has_cpp_attribute(F)
#error "doesn't have fallthrough"
#endif

#if !__has_cpp_attribute(C::F)
#error "doesn't have clang::fallthrough 1"
#endif

#if !__has_cpp_attribute(clang::F)
#error "doesn't have clang::fallthrough 2"
#endif

#if !__has_cpp_attribute(C::fallthrough)
#error "doesn't have clang::fallthrough 3"
#endif

#if !__has_cpp_attribute(CF)
#error "doesn't have clang::fallthrough 4"
#endif

#define FUNCLIKE1(x) clang::x
#if !__has_cpp_attribute(FUNCLIKE1(fallthrough))
#error "doesn't have clang::fallthrough through func-like macro 1"
#endif

#define FUNCLIKE2(x) _Clang::x
#if !__has_cpp_attribute(FUNCLIKE2(fallthrough))
#error "doesn't have clang::fallthrough through func-like macro 2"
#endif
} // namespace cwg2390

namespace cwg2394 { // cwg2394: 15

Expand Down
1 change: 1 addition & 0 deletions clang/test/ClangScanDeps/diagnostics.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ module mod { header "mod.h" }
// CHECK-NEXT: "[[PREFIX]]/mod.h"
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "mod"
// CHECK-NEXT: }
// CHECK-NEXT: ],
Expand Down
4 changes: 4 additions & 0 deletions clang/test/ClangScanDeps/header-search-pruning-transitive.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ module X { header "X.h" }
// CHECK-NEXT: "[[PREFIX]]/X.h",
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "X"
// CHECK-NEXT: },
// CHECK-NEXT: {
Expand All @@ -90,6 +91,7 @@ module X { header "X.h" }
// CHECK-NEXT: "[[PREFIX]]/end/end.h",
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "Y"
// CHECK-NEXT: }
// CHECK-NEXT: ],
Expand Down Expand Up @@ -129,6 +131,7 @@ module X { header "X.h" }
// CHECK-NEXT: "[[PREFIX]]/X.h",
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "X"
// CHECK-NEXT: },
// CHECK-NEXT: {
Expand All @@ -143,6 +146,7 @@ module X { header "X.h" }
// CHECK-NEXT: "[[PREFIX]]/end/end.h",
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "Y"
// CHECK-NEXT: }
// CHECK-NEXT: ],
Expand Down
3 changes: 3 additions & 0 deletions clang/test/ClangScanDeps/header-search-pruning.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
// CHECK_A-NEXT: "context-hash": "{{.*}}",
// CHECK_A-NEXT: "file-deps": [
// CHECK_A: ],
// CHECK_A-NEXT: "link-libraries": [],
// CHECK_A-NEXT: "name": "mod"
// CHECK_A-NEXT: }
// CHECK_A-NEXT: ]
Expand All @@ -55,6 +56,7 @@
// CHECK_B-NEXT: "context-hash": "{{.*}}",
// CHECK_B-NEXT: "file-deps": [
// CHECK_B: ],
// CHECK_B-NEXT: "link-libraries": [],
// CHECK_B-NEXT: "name": "mod"
// CHECK_B-NEXT: }
// CHECK_B-NEXT: ]
Expand All @@ -79,6 +81,7 @@
// CHECK_AB-NEXT: "context-hash": "{{.*}}",
// CHECK_AB-NEXT: "file-deps": [
// CHECK_AB: ],
// CHECK_AB-NEXT: "link-libraries": [],
// CHECK_AB-NEXT: "name": "mod"
// CHECK_AB-NEXT: }
// CHECK_AB-NEXT: ]
Expand Down
121 changes: 121 additions & 0 deletions clang/test/ClangScanDeps/link-libraries.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
// RUN: rm -rf %t
// RUN: mkdir %t
// RUN: mkdir %t/Inputs
// RUN: cp -R %S/Inputs/frameworks %t/Inputs/frameworks
// RUN: split-file %s %t

//--- module.modulemap
module root { header "root.h" }
module direct { header "direct.h" }
module transitive {
header "transitive.h"
link framework "libTransitive"
}
//--- root.h
#include "direct.h"
#include "root/textual.h"
#include "Framework/Framework.h"
//--- direct.h
#include "transitive.h"
//--- transitive.h
// empty

//--- root/textual.h
// This is here to verify that the "root" directory doesn't clash with name of
// the "root" module.

//--- cdb.json.template
[{
"file": "",
"directory": "DIR",
"command": "clang -fmodules -fmodules-cache-path=DIR/cache -FDIR/Inputs/frameworks -I DIR -x c"
}]

// RUN: sed "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json
// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full -module-name=root > %t/result.json
// RUN: cat %t/result.json | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t %s

// CHECK: {
// CHECK-NEXT: "modules": [
// CHECK-NEXT: {
// CHECK-NEXT: "clang-module-deps": [],
// CHECK-NEXT: "clang-modulemap-file": "{{.*}}/__inferred_module.map",
// CHECK-NEXT: "command-line": [
// CHECK: ],
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK-NEXT: "{{.*}}/Framework.h"
// CHECK-NEXT: "{{.*}}/__inferred_module.map"
// CHECK-NEXT: "{{.*}}/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [
// CHECK-NEXT: {
// CHECK-NEXT: "isFramework": true,
// CHECK-NEXT: "link-name": "Framework"
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK-NEXT: "name": "Framework"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "clang-module-deps": [
// CHECK-NEXT: {
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "module-name": "transitive"
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap",
// CHECK-NEXT: "command-line": [
// CHECK: ],
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/direct.h"
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "direct"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "clang-module-deps": [
// CHECK-NEXT: {
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "module-name": "Framework"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "module-name": "direct"
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap",
// CHECK-NEXT: "command-line": [
// CHECK: ],
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/Inputs/frameworks/module.modulemap"
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-NEXT: "[[PREFIX]]/root.h"
// CHECK-NEXT: "[[PREFIX]]/root/textual.h"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "root"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "clang-module-deps": [],
// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap",
// CHECK-NEXT: "command-line": [
// CHECK: ],
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-NEXT: "[[PREFIX]]/transitive.h"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [
// CHECK-NEXT: {
// CHECK-NEXT: "isFramework": true,
// CHECK-NEXT: "link-name": "libTransitive"
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK-NEXT: "name": "transitive"
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK-NEXT: "translation-units": []
// CHECK-NEXT: }
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ framework module FW {
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK: ],
// CHECK-NEXT: "link-libraries": [
// CHECK-NEXT: {
// CHECK-NEXT: "isFramework": true,
// CHECK-NEXT: "link-name": "FW"
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK-NEXT: "name": "FW"
// CHECK-NEXT: }
// CHECK-NEXT: ]
Expand Down
2 changes: 2 additions & 0 deletions clang/test/ClangScanDeps/modules-context-hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
// CHECK-NEXT: "[[PREFIX]]/mod.h",
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "mod"
// CHECK-NEXT: }
// CHECK-NEXT: ],
Expand Down Expand Up @@ -75,6 +76,7 @@
// CHECK-NEXT: "[[PREFIX]]/mod.h",
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "mod"
// CHECK-NEXT: }
// CHECK-NEXT: ],
Expand Down
2 changes: 2 additions & 0 deletions clang/test/ClangScanDeps/modules-dep-args.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ module Direct { header "direct.h" }
// CHECK-NEXT: "[[PREFIX]]/direct.h",
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "Direct"
// CHECK-NEXT: },
// CHECK-NEXT: {
Expand All @@ -73,6 +74,7 @@ module Direct { header "direct.h" }
// CHECK-NEXT: "[[PREFIX]]/module.modulemap",
// CHECK-NEXT: "[[PREFIX]]/transitive.h"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "Transitive"
// CHECK-NEXT: }
// CHECK-NEXT: ],
Expand Down
1 change: 1 addition & 0 deletions clang/test/ClangScanDeps/modules-excluded-header.m
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "Mod"
// CHECK-NEXT: }
// CHECK-NEXT: ]
Expand Down
3 changes: 3 additions & 0 deletions clang/test/ClangScanDeps/modules-extern-submodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ module third {}
// CHECK-NEXT: "[[PREFIX]]/second/second/module.modulemap",
// CHECK-NEXT: "[[PREFIX]]/second/second/sub.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "first"
// CHECK-NEXT: },
// CHECK-NEXT: {
Expand All @@ -76,6 +77,7 @@ module third {}
// CHECK-NEXT: "[[PREFIX]]/second/second/sub.modulemap",
// CHECK-NEXT: "[[PREFIX]]/third/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "second"
// CHECK-NEXT: },
// CHECK-NEXT: {
Expand All @@ -90,6 +92,7 @@ module third {}
// CHECK-NEXT: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/third/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "third"
// CHECK-NEXT: }
// CHECK-NEXT: ],
Expand Down
4 changes: 4 additions & 0 deletions clang/test/ClangScanDeps/modules-extern-unrelated.m
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
// CHECK-NEXT: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/first/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "first"
// CHECK-NEXT: },
// CHECK-NEXT: {
Expand All @@ -52,6 +53,7 @@
// CHECK-NEXT: "[[PREFIX]]/first/first_other.h",
// CHECK-NEXT: "[[PREFIX]]/first/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "first_other"
// CHECK-NEXT: },
// CHECK-NEXT: {
Expand All @@ -71,6 +73,7 @@
// CHECK-NEXT: "[[PREFIX]]/second/second.h",
// CHECK-NEXT: "[[PREFIX]]/second/second.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "second"
// CHECK-NEXT: },
// CHECK-NEXT: {
Expand All @@ -95,6 +98,7 @@
// CHECK-NEXT: "[[PREFIX]]/zeroth/module.modulemap",
// CHECK-NEXT: "[[PREFIX]]/zeroth/zeroth.h"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "zeroth"
// CHECK-NEXT: }
// CHECK-NEXT: ],
Expand Down
1 change: 1 addition & 0 deletions clang/test/ClangScanDeps/modules-file-path-isolation.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
// CHECK-NEXT: "{{.*}}A.h",
// CHECK-NEXT: "{{.*}}module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "A"
// CHECK-NEXT: }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
// CHECK-NEXT: "[[PREFIX]]/Inputs/header2.h",
// CHECK-NEXT: "[[PREFIX]]/Inputs/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "header2"
// CHECK-NEXT: }
// CHECK-NEXT: ],
Expand Down
3 changes: 3 additions & 0 deletions clang/test/ClangScanDeps/modules-full-by-mod-name.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ module transitive { header "transitive.h" }
// CHECK-NEXT: "[[PREFIX]]/direct.h"
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "direct"
// CHECK-NEXT: },
// CHECK-NEXT: {
Expand All @@ -63,6 +64,7 @@ module transitive { header "transitive.h" }
// CHECK-NEXT: "[[PREFIX]]/root.h"
// CHECK-NEXT: "[[PREFIX]]/root/textual.h"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "root"
// CHECK-NEXT: },
// CHECK-NEXT: {
Expand All @@ -75,6 +77,7 @@ module transitive { header "transitive.h" }
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-NEXT: "[[PREFIX]]/transitive.h"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "transitive"
// CHECK-NEXT: }
// CHECK-NEXT: ],
Expand Down
3 changes: 3 additions & 0 deletions clang/test/ClangScanDeps/modules-full.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
// CHECK-NEXT: "[[PREFIX]]/Inputs/header.h",
// CHECK-NEXT: "[[PREFIX]]/Inputs/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "header1"
// CHECK-NEXT: },
// CHECK-NEXT: {
Expand All @@ -62,6 +63,7 @@
// CHECK-NEXT: "[[PREFIX]]/Inputs/header.h",
// CHECK-NEXT: "[[PREFIX]]/Inputs/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "header1"
// CHECK-NEXT: },
// CHECK-NEXT: {
Expand All @@ -80,6 +82,7 @@
// CHECK-NEXT: "[[PREFIX]]/Inputs/header2.h",
// CHECK-NEXT: "[[PREFIX]]/Inputs/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "header2"
// CHECK-NEXT: }
// CHECK-NEXT: ],
Expand Down
6 changes: 6 additions & 0 deletions clang/test/ClangScanDeps/modules-implementation-private.m
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@
// CHECK-NEXT: "[[PREFIX]]/frameworks/FW.framework/Modules/module.private.modulemap",
// CHECK-NEXT: "[[PREFIX]]/frameworks/FW.framework/PrivateHeaders/FW_Private.h"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [
// CHECK-NEXT: {
// CHECK-NEXT: "isFramework": true,
// CHECK-NEXT: "link-name": "FW"
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK-NEXT: "name": "FW_Private"
// CHECK-NEXT: }
// CHECK-NEXT: ],
Expand Down
12 changes: 12 additions & 0 deletions clang/test/ClangScanDeps/modules-implicit-dot-private.m
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@
// CHECK-NEXT: "[[PREFIX]]/frameworks/FW.framework/Headers/FW.h",
// CHECK-NEXT: "[[PREFIX]]/frameworks/FW.framework/Modules/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [
// CHECK-NEXT: {
// CHECK-NEXT: "isFramework": true,
// CHECK-NEXT: "link-name": "FW"
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK-NEXT: "name": "FW"
// CHECK: },
// CHECK: {
Expand All @@ -47,6 +53,12 @@
// CHECK-NEXT: "[[PREFIX]]/frameworks/FW.framework/Modules/module.private.modulemap",
// CHECK-NEXT: "[[PREFIX]]/frameworks/FW.framework/PrivateHeaders/FW_Private.h"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [
// CHECK-NEXT: {
// CHECK-NEXT: "isFramework": true,
// CHECK-NEXT: "link-name": "FW"
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK-NEXT: "name": "FW_Private"
// CHECK: }
// CHECK: ],
Expand Down
25 changes: 25 additions & 0 deletions clang/test/ClangScanDeps/modules-incomplete-umbrella.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ framework module FW_Private {
// CHECK_TU-NEXT: "[[PREFIX]]/frameworks/FW.framework/Headers/FW.h",
// CHECK_TU-NEXT: "[[PREFIX]]/frameworks/FW.framework/Modules/module.modulemap"
// CHECK_TU-NEXT: ],
// CHECK_TU-NEXT: "link-libraries": [
// CHECK_TU-NEXT: {
// CHECK_TU-NEXT: "isFramework": true,
// CHECK_TU-NEXT: "link-name": "FW"
// CHECK_TU-NEXT: }
// CHECK_TU-NEXT: ],
// CHECK_TU-NEXT: "name": "FW"
// CHECK_TU-NEXT: },
// CHECK_TU-NEXT: {
Expand All @@ -60,6 +66,12 @@ framework module FW_Private {
// CHECK_TU-NEXT: "[[PREFIX]]/frameworks/FW.framework/PrivateHeaders/FW_Private.h",
// CHECK_TU-NEXT: "[[PREFIX]]/frameworks/FW.framework/PrivateHeaders/One.h"
// CHECK_TU-NEXT: ],
// CHECK_TU-NEXT: "link-libraries": [
// CHECK_TU-NEXT: {
// CHECK_TU-NEXT: "isFramework": true,
// CHECK_TU-NEXT: "link-name": "FW"
// CHECK_TU-NEXT: }
// CHECK_TU-NEXT: ],
// CHECK_TU-NEXT: "name": "FW_Private"
// CHECK_TU-NEXT: }
// CHECK_TU-NEXT: ],
Expand Down Expand Up @@ -125,6 +137,12 @@ module Mod { header "Mod.h" }
// CHECK_MODULE-NEXT: "[[PREFIX]]/frameworks/FW.framework/Headers/FW.h",
// CHECK_MODULE-NEXT: "[[PREFIX]]/frameworks/FW.framework/Modules/module.modulemap"
// CHECK_MODULE-NEXT: ],
// CHECK_MODULE-NEXT: "link-libraries": [
// CHECK_MODULE-NEXT: {
// CHECK_MODULE-NEXT: "isFramework": true,
// CHECK_MODULE-NEXT: "link-name": "FW"
// CHECK_MODULE-NEXT: }
// CHECK_MODULE-NEXT: ],
// CHECK_MODULE-NEXT: "name": "FW"
// CHECK_MODULE-NEXT: },
// CHECK_MODULE-NEXT: {
Expand All @@ -138,6 +156,12 @@ module Mod { header "Mod.h" }
// CHECK_MODULE-NEXT: "[[PREFIX]]/frameworks/FW.framework/PrivateHeaders/FW_Private.h",
// CHECK_MODULE-NEXT: "[[PREFIX]]/frameworks/FW.framework/PrivateHeaders/One.h"
// CHECK_MODULE-NEXT: ],
// CHECK_MODULE-NEXT: "link-libraries": [
// CHECK_MODULE-NEXT: {
// CHECK_MODULE-NEXT: "isFramework": true,
// CHECK_MODULE-NEXT: "link-name": "FW"
// CHECK_MODULE-NEXT: }
// CHECK_MODULE-NEXT: ],
// CHECK_MODULE-NEXT: "name": "FW_Private"
// CHECK_MODULE-NEXT: },
// CHECK_MODULE-NEXT: {
Expand All @@ -164,6 +188,7 @@ module Mod { header "Mod.h" }
// CHECK_MODULE-NEXT: "[[PREFIX]]/frameworks/FW.framework/PrivateHeaders/Two.h",
// CHECK_MODULE-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK_MODULE-NEXT: ],
// CHECK_MODULE-NEXT: "link-libraries": [],
// CHECK_MODULE-NEXT: "name": "Mod"
// CHECK_MODULE-NEXT: }
// CHECK_MODULE-NEXT: ],
Expand Down
6 changes: 6 additions & 0 deletions clang/test/ClangScanDeps/modules-inferred.m
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@
// CHECK-NEXT: "[[PREFIX]]/frameworks/Inferred.framework/Headers/Inferred.h",
// CHECK-NEXT: "[[PREFIX]]/frameworks/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [
// CHECK-NEXT: {
// CHECK-NEXT: "isFramework": true,
// CHECK-NEXT: "link-name": "Inferred"
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK-NEXT: "name": "Inferred"
// CHECK-NEXT: }
// CHECK-NEXT: ],
Expand Down
1 change: 1 addition & 0 deletions clang/test/ClangScanDeps/modules-no-undeclared-includes.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ module User [no_undeclared_includes] { header "user.h" }
// CHECK-NEXT: "[[PREFIX]]/undeclared/module.modulemap",
// CHECK-NEXT: "[[PREFIX]]/user.h"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "User"
// CHECK-NEXT: }
// CHECK-NEXT: ],
Expand Down
2 changes: 2 additions & 0 deletions clang/test/ClangScanDeps/modules-pch-common-submodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
// CHECK-PCH-NEXT: "[[PREFIX]]/mod_common_sub.h",
// CHECK-PCH-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-PCH-NEXT: ],
// CHECK-PCH-NEXT: "link-libraries": [],
// CHECK-PCH-NEXT: "name": "ModCommon"
// CHECK-PCH-NEXT: }
// CHECK-PCH-NEXT: ],
Expand Down Expand Up @@ -78,6 +79,7 @@
// CHECK-TU-NEXT: "[[PREFIX]]/mod_tu.h",
// CHECK-TU-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-TU-NEXT: ],
// CHECK-TU-NEXT: "link-libraries": [],
// CHECK-TU-NEXT: "name": "ModTU"
// CHECK-TU-NEXT: }
// CHECK-TU-NEXT: ],
Expand Down
2 changes: 2 additions & 0 deletions clang/test/ClangScanDeps/modules-pch-common-via-submodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
// CHECK-PCH-NEXT: "[[PREFIX]]/mod_common.h",
// CHECK-PCH-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-PCH-NEXT: ],
// CHECK-PCH-NEXT: "link-libraries": [],
// CHECK-PCH-NEXT: "name": "ModCommon"
// CHECK-PCH-NEXT: }
// CHECK-PCH-NEXT: ],
Expand Down Expand Up @@ -75,6 +76,7 @@
// CHECK-TU-NEXT: "[[PREFIX]]/mod_tu_sub.h",
// CHECK-TU-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-TU-NEXT: ],
// CHECK-TU-NEXT: "link-libraries": [],
// CHECK-TU-NEXT: "name": "ModTU"
// CHECK-TU-NEXT: }
// CHECK-TU-NEXT: ],
Expand Down
5 changes: 5 additions & 0 deletions clang/test/ClangScanDeps/modules-pch.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
// CHECK-PCH-NEXT: "[[PREFIX]]/mod_common_1.h",
// CHECK-PCH-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-PCH-NEXT: ],
// CHECK-PCH-NEXT: "link-libraries": [],
// CHECK-PCH-NEXT: "name": "ModCommon1"
// CHECK-PCH-NEXT: },
// CHECK-PCH-NEXT: {
Expand All @@ -40,6 +41,7 @@
// CHECK-PCH-NEXT: "[[PREFIX]]/mod_common_2.h",
// CHECK-PCH-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-PCH-NEXT: ],
// CHECK-PCH-NEXT: "link-libraries": [],
// CHECK-PCH-NEXT: "name": "ModCommon2"
// CHECK-PCH-NEXT: },
// CHECK-PCH-NEXT: {
Expand All @@ -57,6 +59,7 @@
// CHECK-PCH-NEXT: "[[PREFIX]]/mod_pch.h",
// CHECK-PCH-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-PCH-NEXT: ],
// CHECK-PCH-NEXT: "link-libraries": [],
// CHECK-PCH-NEXT: "name": "ModPCH"
// CHECK-PCH-NEXT: }
// CHECK-PCH-NEXT: ],
Expand Down Expand Up @@ -113,6 +116,7 @@
// CHECK-TU-NEXT: "[[PREFIX]]/mod_tu.h",
// CHECK-TU-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-TU-NEXT: ],
// CHECK-TU-NEXT: "link-libraries": [],
// CHECK-TU-NEXT: "name": "ModTU"
// CHECK-TU-NEXT: }
// CHECK-TU-NEXT: ],
Expand Down Expand Up @@ -162,6 +166,7 @@
// CHECK-TU-WITH-COMMON-NEXT: "[[PREFIX]]/mod_tu_with_common.h",
// CHECK-TU-WITH-COMMON-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-TU-WITH-COMMON-NEXT: ],
// CHECK-TU-WITH-COMMON-NEXT: "link-libraries": [],
// CHECK-TU-WITH-COMMON-NEXT: "name": "ModTUWithCommon"
// CHECK-TU-WITH-COMMON-NEXT: }
// CHECK-TU-WITH-COMMON-NEXT: ],
Expand Down
13 changes: 13 additions & 0 deletions clang/test/ClangScanDeps/modules-priv-fw-from-pub.m
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
// CHECK-NEXT: "[[PREFIX]]/modules/dependency.h",
// CHECK-NEXT: "[[PREFIX]]/modules/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "Dependency"
// CHECK-NEXT: },
// CHECK-NEXT: {
Expand All @@ -63,6 +64,12 @@
// CHECK-NEXT: "[[PREFIX]]/frameworks/FW.framework/Modules/module.modulemap",
// CHECK-NEXT: "[[PREFIX]]/frameworks/FW.framework/Modules/module.private.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [
// CHECK-NEXT: {
// CHECK-NEXT: "isFramework": true,
// CHECK-NEXT: "link-name": "FW"
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK-NEXT: "name": "FW"
// CHECK-NEXT: },
// CHECK-NEXT: {
Expand All @@ -81,6 +88,12 @@
// CHECK-NEXT: "[[PREFIX]]/frameworks/FW.framework/PrivateHeaders/FW_Private.h",
// CHECK-NEXT: "[[PREFIX]]/modules/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [
// CHECK-NEXT: {
// CHECK-NEXT: "isFramework": true,
// CHECK-NEXT: "link-name": "FW"
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK-NEXT: "name": "FW_Private"
// CHECK-NEXT: }
// CHECK-NEXT: ],
Expand Down
1 change: 1 addition & 0 deletions clang/test/ClangScanDeps/modules-redefinition.m
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
// CHECK-NEXT: [[PREFIX]]/first/module.modulemap",
// CHECK-NEXT: [[PREFIX]]/third/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "first"
// CHECK-NEXT: }
// CHECK: ]
Expand Down
6 changes: 6 additions & 0 deletions clang/test/ClangScanDeps/modules-symlink-dir-vfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ framework module FW { umbrella header "FW.h" }
// CHECK-NEXT: "[[PREFIX]]/copy/Header.h",
// CHECK-NEXT: "[[PREFIX]]/frameworks-symlink/FW.framework/Modules/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [
// CHECK-NEXT: {
// CHECK-NEXT: "isFramework": true,
// CHECK-NEXT: "link-name": "FW"
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK-NEXT: "name": "FW"
// CHECK-NEXT: }
// CHECK-NEXT: ],
Expand Down
1 change: 1 addition & 0 deletions clang/test/ClangScanDeps/modules-transitive.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ module third { header "third.h" }
// CHECK-NEXT: "[[PREFIX]]/first/module.modulemap"
// CHECK-NEXT: "[[PREFIX]]/second/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "first"
// CHECK-NEXT: }
// CHECK: ]
Expand Down
2 changes: 2 additions & 0 deletions clang/test/ClangScanDeps/optimize-canonicalize-macros.m
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "A"
// CHECK-NEXT: },
// CHECK-NEXT: {
Expand All @@ -38,6 +39,7 @@
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "A"
// CHECK-NEXT: }
// CHECK-NEXT: ],
Expand Down
2 changes: 2 additions & 0 deletions clang/test/ClangScanDeps/optimize-fmodulemap.m
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "A"
// CHECK-NEXT: },
// CHECK-NEXT: {
Expand All @@ -35,6 +36,7 @@
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "B"
// CHECK-NEXT: }
// CHECK-NEXT: ],
Expand Down
3 changes: 3 additions & 0 deletions clang/test/ClangScanDeps/optimize-system-warnings.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "A"
// CHECK-NEXT: },
// CHECK-NEXT: {
Expand All @@ -32,6 +33,7 @@
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "B"
// CHECK-NEXT: },
// CHECK-NEXT: {
Expand All @@ -43,6 +45,7 @@
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "C"
// CHECK-NEXT: }
// CHECK-NEXT: ],
Expand Down
5 changes: 4 additions & 1 deletion clang/test/ClangScanDeps/optimize-vfs-leak.m
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "A"
// CHECK-NEXT: },
// CHECK-NEXT: {
Expand All @@ -42,6 +43,7 @@
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "B"
// CHECK-NEXT: },
// CHECK-NEXT: {
Expand All @@ -54,6 +56,7 @@
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "C"
// CHECK-NEXT: }
// CHECK-NEXT: ],
Expand Down Expand Up @@ -102,4 +105,4 @@

//--- moduleC/module.modulemap
module C { header "C.h" }
//--- moduleC/C.h
//--- moduleC/C.h
3 changes: 3 additions & 0 deletions clang/test/ClangScanDeps/optimize-vfs.m
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
// CHECK-NEXT: "[[PREFIX]]/build/A.h",
// CHECK-NEXT: "[[PREFIX]]/build/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "A"
// CHECK-NEXT: },
// CHECK-NEXT: {
Expand All @@ -40,6 +41,7 @@
// CHECK-NEXT: "[[PREFIX]]/modules/B/B.h",
// CHECK-NEXT: "[[PREFIX]]/modules/B/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "B"
// CHECK-NEXT: },
// CHECK-NEXT: {
Expand All @@ -59,6 +61,7 @@
// CHECK-NEXT: "[[PREFIX]]/modules/C/C.h",
// CHECK-NEXT: "[[PREFIX]]/modules/C/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "C"
// CHECK-NEXT: }
// CHECK-NEXT: ],
Expand Down
2 changes: 2 additions & 0 deletions clang/test/ClangScanDeps/removed-args.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
// CHECK-NEXT: "[[PREFIX]]/mod_header.h",
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "ModHeader"
// CHECK-NEXT: },
// CHECK-NEXT: {
Expand All @@ -68,6 +69,7 @@
// CHECK-NEXT: "[[PREFIX]]/mod_tu.h",
// CHECK-NEXT: "[[PREFIX]]/module.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "ModTU"
// CHECK-NEXT: }
// CHECK-NEXT: ],
Expand Down
4 changes: 4 additions & 0 deletions clang/test/ClangScanDeps/working-dir.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "A"
// CHECK-NEXT: },
// CHECK-NEXT: {
Expand All @@ -27,6 +28,7 @@
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "A"
// CHECK-NEXT: },
// CHECK-NEXT: {
Expand All @@ -38,6 +40,7 @@
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "B"
// CHECK-NEXT: },
// CHECK-NEXT: {
Expand All @@ -49,6 +52,7 @@
// CHECK-NEXT: "context-hash": "{{.*}}",
// CHECK-NEXT: "file-deps": [
// CHECK: ],
// CHECK-NEXT: "link-libraries": [],
// CHECK-NEXT: "name": "B"
// CHECK-NEXT: }
// CHECK-NEXT: ],
Expand Down
293 changes: 293 additions & 0 deletions clang/test/CodeGen/amdgpu-variadic-call.c
Original file line number Diff line number Diff line change
@@ -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 [[CONV]]) #[[ATTR2]]
// CHECK-NEXT: ret void
//
void one_f32(int f0, double f1, float v0)
{
sink_0(v0);
sink_1(f0, v0);
sink_2(f1, f0, v0);
}


// Various half types. _Float16 is passed as half and __fp16 as double

// CHECK-LABEL: define {{[^@]+}}@one_f16a
// CHECK-SAME: (i32 noundef [[F0:%.*]], double noundef [[F1:%.*]], half noundef [[V0:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: tail call void (...) @sink_0(half noundef [[V0]]) #[[ATTR2]]
// CHECK-NEXT: tail call void (i32, ...) @sink_1(i32 noundef [[F0]], half noundef [[V0]]) #[[ATTR2]]
// CHECK-NEXT: tail call void (double, i32, ...) @sink_2(double noundef [[F1]], i32 noundef [[F0]], half noundef [[V0]]) #[[ATTR2]]
// CHECK-NEXT: ret void
//
void one_f16a(int f0, double f1, _Float16 v0)
{
sink_0(v0);
sink_1(f0, v0);
sink_2(f1, f0, v0);
}

// CHECK-LABEL: define {{[^@]+}}@one_f16b
// CHECK-SAME: (i32 noundef [[F0:%.*]], double noundef [[F1:%.*]], half noundef [[V0:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[CONV:%.*]] = fpext half [[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 [[CONV]]) #[[ATTR2]]
// CHECK-NEXT: ret void
//
void one_f16b(int f0, double f1, __fp16 v0)
{
sink_0(v0);
sink_1(f0, v0);
sink_2(f1, f0, v0);
}

// CHECK-LABEL: define {{[^@]+}}@one_f16c
// CHECK-SAME: (i32 noundef [[F0:%.*]], double noundef [[F1:%.*]], bfloat noundef [[V0:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: tail call void (...) @sink_0(bfloat noundef [[V0]]) #[[ATTR2]]
// CHECK-NEXT: tail call void (i32, ...) @sink_1(i32 noundef [[F0]], bfloat noundef [[V0]]) #[[ATTR2]]
// CHECK-NEXT: tail call void (double, i32, ...) @sink_2(double noundef [[F1]], i32 noundef [[F0]], bfloat noundef [[V0]]) #[[ATTR2]]
// CHECK-NEXT: ret void
//
void one_f16c(int f0, double f1, __bf16 v0)
{
sink_0(v0);
sink_1(f0, v0);
sink_2(f1, f0, v0);
}

// Simple composites

typedef struct
{
double x0;
double x1;
} pair_f64;

// CHECK-LABEL: define {{[^@]+}}@one_pair_f64
// CHECK-SAME: (i32 noundef [[F0:%.*]], double noundef [[F1:%.*]], double [[V0_COERCE0:%.*]], double [[V0_COERCE1:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[DOTFCA_0_INSERT:%.*]] = insertvalue [[STRUCT_PAIR_F64:%.*]] poison, double [[V0_COERCE0]], 0
// CHECK-NEXT: [[DOTFCA_1_INSERT:%.*]] = insertvalue [[STRUCT_PAIR_F64]] [[DOTFCA_0_INSERT]], double [[V0_COERCE1]], 1
// CHECK-NEXT: tail call void (...) @sink_0([[STRUCT_PAIR_F64]] [[DOTFCA_1_INSERT]]) #[[ATTR2]]
// CHECK-NEXT: tail call void (i32, ...) @sink_1(i32 noundef [[F0]], [[STRUCT_PAIR_F64]] [[DOTFCA_1_INSERT]]) #[[ATTR2]]
// CHECK-NEXT: tail call void (double, i32, ...) @sink_2(double noundef [[F1]], i32 noundef [[F0]], [[STRUCT_PAIR_F64]] [[DOTFCA_1_INSERT]]) #[[ATTR2]]
// CHECK-NEXT: ret void
//
void one_pair_f64(int f0, double f1, pair_f64 v0)
{
sink_0(v0);
sink_1(f0, v0);
sink_2(f1, f0, v0);
}

typedef double v2f64 __attribute__((ext_vector_type(2)));

// CHECK-LABEL: define {{[^@]+}}@one_pair_v2f64
// CHECK-SAME: (i32 noundef [[F0:%.*]], double noundef [[F1:%.*]], <2 x double> noundef [[V0:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: tail call void (...) @sink_0(<2 x double> noundef [[V0]]) #[[ATTR2]]
// CHECK-NEXT: tail call void (i32, ...) @sink_1(i32 noundef [[F0]], <2 x double> noundef [[V0]]) #[[ATTR2]]
// CHECK-NEXT: tail call void (double, i32, ...) @sink_2(double noundef [[F1]], i32 noundef [[F0]], <2 x double> noundef [[V0]]) #[[ATTR2]]
// CHECK-NEXT: ret void
//
void one_pair_v2f64(int f0, double f1, v2f64 v0)
{
sink_0(v0);
sink_1(f0, v0);
sink_2(f1, f0, v0);
}

typedef union
{
float x0;
int x1;
} union_f32_i32;

// CHECK-LABEL: define {{[^@]+}}@one_pair_union_f32_i32
// CHECK-SAME: (i32 noundef [[F0:%.*]], double noundef [[F1:%.*]], i32 [[V0_COERCE:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = bitcast i32 [[V0_COERCE]] to float
// CHECK-NEXT: [[DOTFCA_0_INSERT:%.*]] = insertvalue [[UNION_UNION_F32_I32:%.*]] poison, float [[TMP0]], 0
// CHECK-NEXT: tail call void (...) @sink_0([[UNION_UNION_F32_I32]] [[DOTFCA_0_INSERT]]) #[[ATTR2]]
// CHECK-NEXT: tail call void (i32, ...) @sink_1(i32 noundef [[F0]], [[UNION_UNION_F32_I32]] [[DOTFCA_0_INSERT]]) #[[ATTR2]]
// CHECK-NEXT: tail call void (double, i32, ...) @sink_2(double noundef [[F1]], i32 noundef [[F0]], [[UNION_UNION_F32_I32]] [[DOTFCA_0_INSERT]]) #[[ATTR2]]
// CHECK-NEXT: ret void
//
void one_pair_union_f32_i32(int f0, double f1, union_f32_i32 v0)
{
sink_0(v0);
sink_1(f0, v0);
sink_2(f1, f0, v0);
}

typedef union
{
int x0;
float x1;
} transparent_union_f32_i32 __attribute__((transparent_union));

// CHECK-LABEL: define {{[^@]+}}@one_pair_transparent_union_f32_i32
// CHECK-SAME: (i32 noundef [[F0:%.*]], double noundef [[F1:%.*]], i32 [[V0_COERCE:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[DOTFCA_0_INSERT:%.*]] = insertvalue [[UNION_TRANSPARENT_UNION_F32_I32:%.*]] poison, i32 [[V0_COERCE]], 0
// CHECK-NEXT: tail call void (...) @sink_0([[UNION_TRANSPARENT_UNION_F32_I32]] [[DOTFCA_0_INSERT]]) #[[ATTR2]]
// CHECK-NEXT: tail call void (i32, ...) @sink_1(i32 noundef [[F0]], [[UNION_TRANSPARENT_UNION_F32_I32]] [[DOTFCA_0_INSERT]]) #[[ATTR2]]
// CHECK-NEXT: tail call void (double, i32, ...) @sink_2(double noundef [[F1]], i32 noundef [[F0]], [[UNION_TRANSPARENT_UNION_F32_I32]] [[DOTFCA_0_INSERT]]) #[[ATTR2]]
// CHECK-NEXT: ret void
//
void one_pair_transparent_union_f32_i32(int f0, double f1, transparent_union_f32_i32 v0)
{
sink_0(v0);
sink_1(f0, v0);
sink_2(f1, f0, v0);
}

// Passing multiple values in the variadic pack

// CHECK-LABEL: define {{[^@]+}}@multiple_one
// CHECK-SAME: (i32 noundef [[F0:%.*]], double noundef [[F1:%.*]], i32 noundef [[V0:%.*]], double noundef [[V1:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: tail call void (...) @sink_0(i32 noundef [[V0]], double noundef [[V1]]) #[[ATTR2]]
// CHECK-NEXT: tail call void (i32, ...) @sink_1(i32 noundef [[F0]], i32 noundef [[V0]], double noundef [[V1]]) #[[ATTR2]]
// CHECK-NEXT: tail call void (double, i32, ...) @sink_2(double noundef [[F1]], i32 noundef [[F0]], i32 noundef [[V0]], double noundef [[V1]]) #[[ATTR2]]
// CHECK-NEXT: ret void
//
void multiple_one(int f0, double f1, int v0, double v1)
{
sink_0(v0, v1);
sink_1(f0, v0, v1);
sink_2(f1, f0, v0, v1);
}

// CHECK-LABEL: define {{[^@]+}}@multiple_two
// CHECK-SAME: (i32 noundef [[F0:%.*]], double noundef [[F1:%.*]], double [[V0_COERCE0:%.*]], double [[V0_COERCE1:%.*]], float noundef [[V1:%.*]], i32 [[V2_COERCE:%.*]], i32 noundef [[V3:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = bitcast i32 [[V2_COERCE]] to float
// CHECK-NEXT: [[CONV:%.*]] = fpext float [[V1]] to double
// CHECK-NEXT: [[DOTFCA_0_INSERT16:%.*]] = insertvalue [[STRUCT_PAIR_F64:%.*]] poison, double [[V0_COERCE0]], 0
// CHECK-NEXT: [[DOTFCA_1_INSERT:%.*]] = insertvalue [[STRUCT_PAIR_F64]] [[DOTFCA_0_INSERT16]], double [[V0_COERCE1]], 1
// CHECK-NEXT: [[DOTFCA_0_INSERT:%.*]] = insertvalue [[UNION_UNION_F32_I32:%.*]] poison, float [[TMP0]], 0
// CHECK-NEXT: tail call void (...) @sink_0([[STRUCT_PAIR_F64]] [[DOTFCA_1_INSERT]], double noundef [[CONV]], [[UNION_UNION_F32_I32]] [[DOTFCA_0_INSERT]], i32 noundef [[V3]]) #[[ATTR2]]
// CHECK-NEXT: tail call void (i32, ...) @sink_1(i32 noundef [[F0]], [[STRUCT_PAIR_F64]] [[DOTFCA_1_INSERT]], double noundef [[CONV]], [[UNION_UNION_F32_I32]] [[DOTFCA_0_INSERT]], i32 noundef [[V3]]) #[[ATTR2]]
// CHECK-NEXT: tail call void (double, i32, ...) @sink_2(double noundef [[F1]], i32 noundef [[F0]], [[STRUCT_PAIR_F64]] [[DOTFCA_1_INSERT]], double noundef [[CONV]], [[UNION_UNION_F32_I32]] [[DOTFCA_0_INSERT]], i32 noundef [[V3]]) #[[ATTR2]]
// CHECK-NEXT: ret void
//
void multiple_two(int f0, double f1, pair_f64 v0, float v1, union_f32_i32 v2, int v3)
{
sink_0(v0, v1, v2, v3);
sink_1(f0, v0, v1, v2, v3);
sink_2(f1, f0, v0, v1, v2, v3);
}
4 changes: 2 additions & 2 deletions clang/test/Driver/mips-mti-linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// the --gcc-toolchain one.

// = Big-endian, mips32r2, hard float
// RUN: %clang -### %s 2>&1 \
// RUN: %clang -### -no-canonical-prefixes %s 2>&1 \
// RUN: --target=mips-mti-linux -mips32r2 -mhard-float -no-pie \
// RUN: -rtlib=platform -fuse-ld=ld \
// RUN: --sysroot=%S/Inputs/mips_mti_linux/sysroot \
Expand All @@ -25,7 +25,7 @@
// CHECK-BE-HF-32R2-SAME: "[[SYSROOT]]/mips-r2-hard-musl/usr/lib{{/|\\\\}}crtn.o"

// = Little-endian, mips32r2, hard float
// RUN: %clang -### %s 2>&1 \
// RUN: %clang -### -no-canonical-prefixes %s 2>&1 \
// RUN: --target=mips-mti-linux -mips32r2 -EL -mhard-float -no-pie \
// RUN: -rtlib=platform -fuse-ld=ld \
// RUN: --sysroot=%S/Inputs/mips_mti_linux/sysroot \
Expand Down
6 changes: 3 additions & 3 deletions clang/test/Driver/openmp-offload-gpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,21 +70,21 @@

/// Check that the runtime bitcode library is part of the compile line.
/// Create a bogus bitcode library and specify it with libomptarget-nvptx-bc-path
// RUN: %clang -### -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda \
// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda \
// RUN: --libomptarget-nvptx-bc-path=%S/Inputs/libomptarget/libomptarget-nvptx-test.bc \
// RUN: -Xopenmp-target -march=sm_52 --cuda-path=%S/Inputs/CUDA_102/usr/local/cuda \
// RUN: -fopenmp-relocatable-target -save-temps %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHK-BCLIB %s

/// Specify the directory containing the bitcode lib, check clang picks the right one
// RUN: %clang -### -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda \
// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda \
// RUN: --libomptarget-nvptx-bc-path=%S/Inputs/libomptarget \
// RUN: -Xopenmp-target -march=sm_52 --cuda-path=%S/Inputs/CUDA_102/usr/local/cuda \
// RUN: -fopenmp-relocatable-target -save-temps \
// RUN: %s 2>&1 | FileCheck -check-prefix=CHK-BCLIB-DIR %s

/// Create a bogus bitcode library and find it with LIBRARY_PATH
// RUN: env LIBRARY_PATH=%S/Inputs/libomptarget/subdir %clang -### -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda \
// RUN: env LIBRARY_PATH=%S/Inputs/libomptarget/subdir %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda \
// RUN: -Xopenmp-target -march=sm_52 --cuda-path=%S/Inputs/CUDA_102/usr/local/cuda \
// RUN: -fopenmp-relocatable-target -save-temps \
// RUN: %s 2>&1 | FileCheck -check-prefix=CHK-ENV-BCLIB %s
Expand Down
14 changes: 7 additions & 7 deletions clang/test/Driver/openmp-offload.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,55 +35,55 @@
/// ###########################################################################

/// Check -Xopenmp-target=powerpc64le-ibm-linux-gnu -mcpu=pwr7 is passed when compiling for the device.
// RUN: %clang -### -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu -Xopenmp-target=powerpc64le-ibm-linux-gnu -mcpu=pwr7 %s 2>&1 \
// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu -Xopenmp-target=powerpc64le-ibm-linux-gnu -mcpu=pwr7 %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHK-FOPENMP-EQ-TARGET %s

// CHK-FOPENMP-EQ-TARGET: clang{{.*}} "-target-cpu" "pwr7" {{.*}}"-fopenmp-is-target-device"

/// ###########################################################################

/// Check -Xopenmp-target -mcpu=pwr7 is passed when compiling for the device.
// RUN: %clang -### -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu -Xopenmp-target -mcpu=pwr7 %s 2>&1 \
// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu -Xopenmp-target -mcpu=pwr7 %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHK-FOPENMP-TARGET %s

// CHK-FOPENMP-TARGET: clang{{.*}} "-target-cpu" "pwr7" {{.*}}"-fopenmp-is-target-device"

/// ##########################################################################

/// Check -mcpu=pwr7 is passed to the same triple.
// RUN: %clang -### -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu --target=powerpc64le-ibm-linux-gnu -mcpu=pwr7 %s 2>&1 \
// RUN: %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu --target=powerpc64le-ibm-linux-gnu -mcpu=pwr7 %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHK-FOPENMP-MCPU-TO-SAME-TRIPLE %s

// CHK-FOPENMP-MCPU-TO-SAME-TRIPLE: clang{{.*}} "-target-cpu" "pwr7" {{.*}}"-fopenmp-is-target-device"

/// ##########################################################################

/// Check -march=pwr7 is NOT passed to nvptx64-nvidia-cuda.
// RUN: not %clang -### -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda --target=powerpc64le-ibm-linux-gnu -march=pwr7 %s 2>&1 \
// RUN: not %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda --target=powerpc64le-ibm-linux-gnu -march=pwr7 %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHK-FOPENMP-MARCH-TO-GPU %s

// CHK-FOPENMP-MARCH-TO-GPU-NOT: clang{{.*}} "-target-cpu" "pwr7" {{.*}}"-fopenmp-is-target-device"

/// ###########################################################################

/// Check -march=pwr7 is NOT passed to x86_64-unknown-linux-gnu.
// RUN: not %clang -### -fopenmp=libomp -fopenmp-targets=x86_64-unknown-linux-gnu --target=powerpc64le-ibm-linux-gnu -march=pwr7 %s 2>&1 \
// RUN: not %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=x86_64-unknown-linux-gnu --target=powerpc64le-ibm-linux-gnu -march=pwr7 %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHK-FOPENMP-MARCH-TO-X86 %s

// CHK-FOPENMP-MARCH-TO-X86-NOT: clang{{.*}} "-target-cpu" "pwr7" {{.*}}"-fopenmp-is-target-device"

/// ###########################################################################

/// Check -Xopenmp-target triggers error when multiple triples are used.
// RUN: not %clang -### -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu,powerpc64le-unknown-linux-gnu -Xopenmp-target -mcpu=pwr8 %s 2>&1 \
// RUN: not %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu,powerpc64le-unknown-linux-gnu -Xopenmp-target -mcpu=pwr8 %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHK-FOPENMP-TARGET-AMBIGUOUS-ERROR %s

// CHK-FOPENMP-TARGET-AMBIGUOUS-ERROR: clang{{.*}} error: cannot deduce implicit triple value for -Xopenmp-target, specify triple using -Xopenmp-target=<triple>

/// ###########################################################################

/// Check -Xopenmp-target triggers error when an option requiring arguments is passed to it.
// RUN: not %clang -### -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu -Xopenmp-target -Xopenmp-target -mcpu=pwr8 %s 2>&1 \
// RUN: not %clang -### -no-canonical-prefixes -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu -Xopenmp-target -Xopenmp-target -mcpu=pwr8 %s 2>&1 \
// RUN: | FileCheck -check-prefix=CHK-FOPENMP-TARGET-NESTED-ERROR %s

// CHK-FOPENMP-TARGET-NESTED-ERROR: clang{{.*}} error: invalid -Xopenmp-target argument: '-Xopenmp-target -Xopenmp-target', options requiring arguments are unsupported
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Driver/ve-toolchain.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
/// - nld VE specific options
/// - sjlj exception

// RUN: %clang -### --target=ve-unknown-linux-gnu \
// RUN: %clang -### -no-canonical-prefixes --target=ve-unknown-linux-gnu \
// RUN: --sysroot %S/Inputs/basic_ve_tree \
// RUN: -resource-dir=%S/Inputs/basic_ve_tree/resource_dir \
// RUN: --unwindlib=none \
Expand Down
21 changes: 21 additions & 0 deletions clang/test/Interpreter/execute.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// REQUIRES: host-supports-jit
// UNSUPPORTED: system-aix

// RUN: cat %s | clang-repl -Xcc -xc -Xcc -Xclang -Xcc -verify | FileCheck %s
// RUN: cat %s | clang-repl -Xcc -xc -Xcc -O2 -Xcc -Xclang -Xcc -verify| FileCheck %s
int printf(const char *, ...);
int i = 42; err // expected-error{{use of undeclared identifier}}
int i = 42;
struct S { float f; struct S *m;} s = {1.0, 0};
// FIXME: Making foo inline fails to emit the function.
int foo() { return 42; }
void run() { \
printf("i = %d\n", i); \
printf("S[f=%f, m=0x%llx]\n", s.f, (unsigned long long)s.m); \
int r3 = foo(); \
}
run();
// CHECK: i = 42
// CHECK-NEXT: S[f=1.000000, m=0x0]

%quit
22 changes: 17 additions & 5 deletions clang/test/Lexer/cxx2c-raw-strings.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Wc++26-extensions %s
// RUN: %clang_cc1 -std=c++2c -fsyntax-only -verify=cxx26 -Wpre-c++26-compat %s
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify=precxx26,expected -Wc++26-extensions %s
// RUN: %clang_cc1 -std=c++2c -fsyntax-only -verify=cxx26,expected -Wpre-c++26-compat %s

int main() {
(void) R"abc`@$(foobar)abc`@$";
//expected-warning@-1 {{'`' in a raw string literal delimiter is a C++2c extension}}
//expected-warning@-2 {{'@' in a raw string literal delimiter is a C++2c extension}}
//expected-warning@-3 {{'$' in a raw string literal delimiter is a C++2c extension}}
//precxx26-warning@-1 {{'`' in a raw string literal delimiter is a C++2c extension}}
//precxx26-warning@-2 {{'@' in a raw string literal delimiter is a C++2c extension}}
//precxx26-warning@-3 {{'$' in a raw string literal delimiter is a C++2c extension}}
//cxx26-warning@-4 {{'`' in a raw string literal delimiter is incompatible with standards before C++2c}}
//cxx26-warning@-5 {{'@' in a raw string literal delimiter is incompatible with standards before C++2c}}
//cxx26-warning@-6 {{'$' in a raw string literal delimiter is incompatible with standards before C++2c}}

(void) R"\t()\t";
// expected-error@-1 {{invalid character '\' in raw string delimiter}}
// expected-error@-2 {{expected expression}}

(void) R" () ";
// expected-error@-1 {{invalid character ' ' in raw string delimiter}}
// expected-error@-2 {{expected expression}}

(void) R"\()\";
// expected-error@-1 {{invalid character '\' in raw string delimiter}}
// expected-error@-2 {{expected expression}}
}
Loading