21 changes: 20 additions & 1 deletion clang/lib/CodeGen/CGExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1937,7 +1937,26 @@ Value *ScalarExprEmitter::VisitMemberExpr(MemberExpr *E) {
}
}

return EmitLoadOfLValue(E);
llvm::Value *Result = EmitLoadOfLValue(E);

// If -fdebug-info-for-profiling is specified, emit a pseudo variable and its
// debug info for the pointer, even if there is no variable associated with
// the pointer's expression.
if (CGF.CGM.getCodeGenOpts().DebugInfoForProfiling && CGF.getDebugInfo()) {
if (llvm::LoadInst *Load = dyn_cast<llvm::LoadInst>(Result)) {
if (llvm::GetElementPtrInst *GEP =
dyn_cast<llvm::GetElementPtrInst>(Load->getPointerOperand())) {
if (llvm::Instruction *Pointer =
dyn_cast<llvm::Instruction>(GEP->getPointerOperand())) {
QualType Ty = E->getBase()->getType();
if (!E->isArrow())
Ty = CGF.getContext().getPointerType(Ty);
CGF.getDebugInfo()->EmitPseudoVariable(Builder, Pointer, Ty);
}
}
}
}
return Result;
}

Value *ScalarExprEmitter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/CodeGen/CodeGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -4635,6 +4635,9 @@ class CodeGenFunction : public CodeGenTypeCache {
llvm::Value *EmitHexagonBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
llvm::Value *EmitRISCVBuiltinExpr(unsigned BuiltinID, const CallExpr *E,
ReturnValueSlot ReturnValue);

void AddAMDGPUFenceAddressSpaceMMRA(llvm::Instruction *Inst,
const CallExpr *E);
void ProcessOrderScopeAMDGCN(llvm::Value *Order, llvm::Value *Scope,
llvm::AtomicOrdering &AO,
llvm::SyncScope::ID &SSID);
Expand Down
12 changes: 12 additions & 0 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5341,6 +5341,18 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
!IsDefinitionAvailableExternally &&
D->needsDestruction(getContext()) == QualType::DK_cxx_destructor;

// It is helpless to emit the definition for an available_externally variable
// which can't be marked as const.
// We don't need to check if it needs global ctor or dtor. See the above
// comment for ideas.
if (IsDefinitionAvailableExternally &&
(!D->hasConstantInitialization() ||
// TODO: Update this when we have interface to check constexpr
// destructor.
D->needsDestruction(getContext()) ||
!D->getType().isConstantStorage(getContext(), true, true)))
return;

const VarDecl *InitDecl;
const Expr *InitExpr = D->getAnyInitializer(InitDecl);

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CodeGenPGO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1340,7 +1340,7 @@ void CodeGenPGO::setProfileVersion(llvm::Module &M) {
llvm::APInt(64, ProfileVersion)),
VarName);

IRLevelVersionVariable->setVisibility(llvm::GlobalValue::DefaultVisibility);
IRLevelVersionVariable->setVisibility(llvm::GlobalValue::HiddenVisibility);
llvm::Triple TT(M.getTargetTriple());
if (TT.supportsCOMDAT()) {
IRLevelVersionVariable->setLinkage(llvm::GlobalValue::ExternalLinkage);
Expand Down
15 changes: 15 additions & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/BinaryFormat/Magic.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Frontend/Debug/Options.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/CodeGen.h"
Expand Down Expand Up @@ -4642,6 +4643,7 @@ renderDebugOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T,
Args.addOptInFlag(CmdArgs, options::OPT_fforce_dwarf_frame,
options::OPT_fno_force_dwarf_frame);

bool EnableTypeUnits = false;
if (Args.hasFlag(options::OPT_fdebug_types_section,
options::OPT_fno_debug_types_section, false)) {
if (!(T.isOSBinFormatELF() || T.isOSBinFormatWasm())) {
Expand All @@ -4652,11 +4654,24 @@ renderDebugOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T,
} else if (checkDebugInfoOption(
Args.getLastArg(options::OPT_fdebug_types_section), Args, D,
TC)) {
EnableTypeUnits = true;
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-generate-type-units");
}
}

if (const Arg *A =
Args.getLastArg(options::OPT_gomit_unreferenced_methods,
options::OPT_gno_omit_unreferenced_methods))
(void)checkDebugInfoOption(A, Args, D, TC);
if (Args.hasFlag(options::OPT_gomit_unreferenced_methods,
options::OPT_gno_omit_unreferenced_methods, false) &&
(DebugInfoKind == llvm::codegenoptions::DebugInfoConstructor ||
DebugInfoKind == llvm::codegenoptions::LimitedDebugInfo) &&
!EnableTypeUnits) {
CmdArgs.push_back("-gomit-unreferenced-methods");
}

// To avoid join/split of directory+filename, the integrated assembler prefers
// the directory form of .file on all DWARF versions. GNU as doesn't allow the
// form before DWARF v5.
Expand Down
98 changes: 62 additions & 36 deletions clang/lib/Driver/ToolChains/Gnu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -672,12 +672,41 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
}

// Facebook T92898286
if (Args.hasArg(options::OPT_post_link_optimize))
CmdArgs.push_back("-q");
// End Facebook T92898286

Args.AddAllArgs(CmdArgs, options::OPT_T);

const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
C.addCommand(std::make_unique<Command>(JA, *this,
ResponseFileSupport::AtFileCurCP(),
Exec, CmdArgs, Inputs, Output));
// Facebook T92898286
if (!Args.hasArg(options::OPT_post_link_optimize) || !Output.isFilename())
return;

const char *MvExec = Args.MakeArgString(ToolChain.GetProgramPath("mv"));
ArgStringList MoveCmdArgs;
MoveCmdArgs.push_back(Output.getFilename());
const char *PreBoltBin =
Args.MakeArgString(Twine(Output.getFilename()) + ".pre-bolt");
MoveCmdArgs.push_back(PreBoltBin);
C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
MvExec, MoveCmdArgs, std::nullopt));

ArgStringList BoltCmdArgs;
const char *BoltExec =
Args.MakeArgString(ToolChain.GetProgramPath("llvm-bolt"));
BoltCmdArgs.push_back(PreBoltBin);
BoltCmdArgs.push_back("-reorder-blocks=reverse");
BoltCmdArgs.push_back("-update-debug-sections");
BoltCmdArgs.push_back("-o");
BoltCmdArgs.push_back(Output.getFilename());
C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
BoltExec, BoltCmdArgs, std::nullopt));
// End Facebook T92898286
}

void tools::gnutools::Assembler::ConstructJob(Compilation &C,
Expand Down Expand Up @@ -2227,10 +2256,19 @@ void Generic_GCC::GCCInstallationDetector::init(
SmallVector<StringRef, 16> CandidateBiarchTripleAliases;
// Add some triples that we want to check first.
CandidateTripleAliases.push_back(TargetTriple.str());
std::string TripleNoVendor = TargetTriple.getArchName().str() + "-" +
TargetTriple.getOSAndEnvironmentName().str();
if (TargetTriple.getVendor() == llvm::Triple::UnknownVendor)
std::string TripleNoVendor, BiarchTripleNoVendor;
if (TargetTriple.getVendor() == llvm::Triple::UnknownVendor) {
StringRef OSEnv = TargetTriple.getOSAndEnvironmentName();
if (TargetTriple.getEnvironment() == llvm::Triple::GNUX32)
OSEnv = "linux-gnu";
TripleNoVendor = (TargetTriple.getArchName().str() + '-' + OSEnv).str();
CandidateTripleAliases.push_back(TripleNoVendor);
if (BiarchVariantTriple.getArch() != llvm::Triple::UnknownArch) {
BiarchTripleNoVendor =
(BiarchVariantTriple.getArchName().str() + '-' + OSEnv).str();
CandidateBiarchTripleAliases.push_back(BiarchTripleNoVendor);
}
}

CollectLibDirsAndTriples(TargetTriple, BiarchVariantTriple, CandidateLibDirs,
CandidateTripleAliases, CandidateBiarchLibDirs,
Expand Down Expand Up @@ -2453,11 +2491,9 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
// lists should shrink over time. Please don't add more elements to *Triples.
static const char *const AArch64LibDirs[] = {"/lib64", "/lib"};
static const char *const AArch64Triples[] = {
"aarch64-none-linux-gnu", "aarch64-linux-gnu", "aarch64-redhat-linux",
"aarch64-suse-linux"};
"aarch64-none-linux-gnu", "aarch64-redhat-linux", "aarch64-suse-linux"};
static const char *const AArch64beLibDirs[] = {"/lib"};
static const char *const AArch64beTriples[] = {"aarch64_be-none-linux-gnu",
"aarch64_be-linux-gnu"};
static const char *const AArch64beTriples[] = {"aarch64_be-none-linux-gnu"};

static const char *const ARMLibDirs[] = {"/lib"};
static const char *const ARMTriples[] = {"arm-linux-gnueabi"};
Expand All @@ -2482,9 +2518,8 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
"x86_64-linux-gnu", "x86_64-unknown-linux-gnu",
"x86_64-pc-linux-gnu", "x86_64-redhat-linux6E",
"x86_64-redhat-linux", "x86_64-suse-linux",
"x86_64-manbo-linux-gnu", "x86_64-linux-gnu",
"x86_64-slackware-linux", "x86_64-unknown-linux",
"x86_64-amazon-linux"};
"x86_64-manbo-linux-gnu", "x86_64-slackware-linux",
"x86_64-unknown-linux", "x86_64-amazon-linux"};
static const char *const X32Triples[] = {"x86_64-linux-gnux32",
"x86_64-pc-linux-gnux32"};
static const char *const X32LibDirs[] = {"/libx32", "/lib"};
Expand All @@ -2500,26 +2535,24 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
"loongarch64-linux-gnu", "loongarch64-unknown-linux-gnu"};

static const char *const M68kLibDirs[] = {"/lib"};
static const char *const M68kTriples[] = {
"m68k-linux-gnu", "m68k-unknown-linux-gnu", "m68k-suse-linux"};
static const char *const M68kTriples[] = {"m68k-unknown-linux-gnu",
"m68k-suse-linux"};

static const char *const MIPSLibDirs[] = {"/libo32", "/lib"};
static const char *const MIPSTriples[] = {
"mips-linux-gnu", "mips-mti-linux", "mips-mti-linux-gnu",
"mips-img-linux-gnu", "mipsisa32r6-linux-gnu"};
static const char *const MIPSELLibDirs[] = {"/libo32", "/lib"};
static const char *const MIPSELTriples[] = {
"mipsel-linux-gnu", "mips-img-linux-gnu", "mipsisa32r6el-linux-gnu"};
static const char *const MIPSELTriples[] = {"mipsel-linux-gnu",
"mips-img-linux-gnu"};

static const char *const MIPS64LibDirs[] = {"/lib64", "/lib"};
static const char *const MIPS64Triples[] = {
"mips64-linux-gnu", "mips-mti-linux-gnu",
"mips-img-linux-gnu", "mips64-linux-gnuabi64",
"mips-mti-linux-gnu", "mips-img-linux-gnu", "mips64-linux-gnuabi64",
"mipsisa64r6-linux-gnu", "mipsisa64r6-linux-gnuabi64"};
static const char *const MIPS64ELLibDirs[] = {"/lib64", "/lib"};
static const char *const MIPS64ELTriples[] = {
"mips64el-linux-gnu", "mips-mti-linux-gnu",
"mips-img-linux-gnu", "mips64el-linux-gnuabi64",
"mips-mti-linux-gnu", "mips-img-linux-gnu", "mips64el-linux-gnuabi64",
"mipsisa64r6el-linux-gnu", "mipsisa64r6el-linux-gnuabi64"};

static const char *const MIPSN32LibDirs[] = {"/lib32"};
Expand All @@ -2534,46 +2567,39 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(

static const char *const PPCLibDirs[] = {"/lib32", "/lib"};
static const char *const PPCTriples[] = {
"powerpc-linux-gnu", "powerpc-unknown-linux-gnu", "powerpc-linux-gnuspe",
"powerpc-unknown-linux-gnu",
// On 32-bit PowerPC systems running SUSE Linux, gcc is configured as a
// 64-bit compiler which defaults to "-m32", hence "powerpc64-suse-linux".
"powerpc64-suse-linux", "powerpc-montavista-linuxspe"};
static const char *const PPCLELibDirs[] = {"/lib32", "/lib"};
static const char *const PPCLETriples[] = {"powerpcle-linux-gnu",
"powerpcle-unknown-linux-gnu",
static const char *const PPCLETriples[] = {"powerpcle-unknown-linux-gnu",
"powerpcle-linux-musl"};

static const char *const PPC64LibDirs[] = {"/lib64", "/lib"};
static const char *const PPC64Triples[] = {
"powerpc64-linux-gnu", "powerpc64-unknown-linux-gnu",
"powerpc64-suse-linux", "ppc64-redhat-linux"};
static const char *const PPC64Triples[] = {"powerpc64-unknown-linux-gnu",
"powerpc64-suse-linux",
"ppc64-redhat-linux"};
static const char *const PPC64LELibDirs[] = {"/lib64", "/lib"};
static const char *const PPC64LETriples[] = {
"powerpc64le-linux-gnu", "powerpc64le-unknown-linux-gnu",
"powerpc64le-none-linux-gnu", "powerpc64le-suse-linux",
"ppc64le-redhat-linux"};
"powerpc64le-unknown-linux-gnu", "powerpc64le-none-linux-gnu",
"powerpc64le-suse-linux", "ppc64le-redhat-linux"};

static const char *const RISCV32LibDirs[] = {"/lib32", "/lib"};
static const char *const RISCV32Triples[] = {"riscv32-unknown-linux-gnu",
"riscv32-linux-gnu",
"riscv32-unknown-elf"};
static const char *const RISCV64LibDirs[] = {"/lib64", "/lib"};
static const char *const RISCV64Triples[] = {"riscv64-unknown-linux-gnu",
"riscv64-linux-gnu",
"riscv64-unknown-elf"};

static const char *const SPARCv8LibDirs[] = {"/lib32", "/lib"};
static const char *const SPARCv8Triples[] = {"sparc-linux-gnu",
"sparcv8-linux-gnu"};
static const char *const SPARCv8Triples[] = {"sparcv8-linux-gnu"};
static const char *const SPARCv9LibDirs[] = {"/lib64", "/lib"};
static const char *const SPARCv9Triples[] = {"sparc64-linux-gnu",
"sparcv9-linux-gnu"};
static const char *const SPARCv9Triples[] = {"sparcv9-linux-gnu"};

static const char *const SystemZLibDirs[] = {"/lib64", "/lib"};
static const char *const SystemZTriples[] = {
"s390x-linux-gnu", "s390x-unknown-linux-gnu", "s390x-ibm-linux-gnu",
"s390x-suse-linux", "s390x-redhat-linux"};

"s390x-unknown-linux-gnu", "s390x-ibm-linux-gnu", "s390x-suse-linux",
"s390x-redhat-linux"};

using std::begin;
using std::end;
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Driver/ToolChains/HIPUtility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,9 @@ class HIPUndefinedFatBinSymbols {
std::string ID = IA->getId().str();
if (!ID.empty()) {
ID = llvm::utohexstr(llvm::MD5Hash(ID), /*LowerCase=*/true);
FatBinSymbols.insert(Twine(FatBinPrefix + "_" + ID).str());
FatBinSymbols.insert((FatBinPrefix + Twine('_') + ID).str());
GPUBinHandleSymbols.insert(
Twine(GPUBinHandlePrefix + "_" + ID).str());
(GPUBinHandlePrefix + Twine('_') + ID).str());
continue;
}
if (IA->getInputArg().getNumValues() == 0)
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Format/Format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ struct ScalarEnumerationTraits<FormatStyle::EscapedNewlineAlignmentStyle> {
FormatStyle::EscapedNewlineAlignmentStyle &Value) {
IO.enumCase(Value, "DontAlign", FormatStyle::ENAS_DontAlign);
IO.enumCase(Value, "Left", FormatStyle::ENAS_Left);
IO.enumCase(Value, "LeftWithLastLine", FormatStyle::ENAS_LeftWithLastLine);
IO.enumCase(Value, "Right", FormatStyle::ENAS_Right);

// For backward compatibility.
Expand Down
29 changes: 18 additions & 11 deletions clang/lib/Format/WhitespaceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1245,22 +1245,29 @@ void WhitespaceManager::alignTrailingComments(unsigned Start, unsigned End,
}

void WhitespaceManager::alignEscapedNewlines() {
if (Style.AlignEscapedNewlines == FormatStyle::ENAS_DontAlign)
const auto Align = Style.AlignEscapedNewlines;
if (Align == FormatStyle::ENAS_DontAlign)
return;

bool AlignLeft = Style.AlignEscapedNewlines == FormatStyle::ENAS_Left;
unsigned MaxEndOfLine = AlignLeft ? 0 : Style.ColumnLimit;
const bool WithLastLine = Align == FormatStyle::ENAS_LeftWithLastLine;
const bool AlignLeft = Align == FormatStyle::ENAS_Left || WithLastLine;
const auto MaxColumn = Style.ColumnLimit;
unsigned MaxEndOfLine = AlignLeft ? 0 : MaxColumn;
unsigned StartOfMacro = 0;
for (unsigned i = 1, e = Changes.size(); i < e; ++i) {
Change &C = Changes[i];
if (C.NewlinesBefore > 0) {
if (C.ContinuesPPDirective) {
MaxEndOfLine = std::max(C.PreviousEndOfTokenColumn + 2, MaxEndOfLine);
} else {
alignEscapedNewlines(StartOfMacro + 1, i, MaxEndOfLine);
MaxEndOfLine = AlignLeft ? 0 : Style.ColumnLimit;
StartOfMacro = i;
}
if (C.NewlinesBefore == 0 && (!WithLastLine || C.Tok->isNot(tok::eof)))
continue;
const bool InPPDirective = C.ContinuesPPDirective;
const auto BackslashColumn = C.PreviousEndOfTokenColumn + 2;
if (InPPDirective ||
(WithLastLine && (MaxColumn == 0 || BackslashColumn <= MaxColumn))) {
MaxEndOfLine = std::max(BackslashColumn, MaxEndOfLine);
}
if (!InPPDirective) {
alignEscapedNewlines(StartOfMacro + 1, i, MaxEndOfLine);
MaxEndOfLine = AlignLeft ? 0 : MaxColumn;
StartOfMacro = i;
}
}
alignEscapedNewlines(StartOfMacro + 1, Changes.size(), MaxEndOfLine);
Expand Down
58 changes: 41 additions & 17 deletions clang/lib/Interpreter/Interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,12 +229,32 @@ IncrementalCompilerBuilder::CreateCudaHost() {
}

Interpreter::Interpreter(std::unique_ptr<CompilerInstance> CI,
llvm::Error &Err) {
llvm::ErrorAsOutParameter EAO(&Err);
llvm::Error &ErrOut,
std::unique_ptr<llvm::orc::LLJITBuilder> JITBuilder)
: JITBuilder(std::move(JITBuilder)) {
llvm::ErrorAsOutParameter EAO(&ErrOut);
auto LLVMCtx = std::make_unique<llvm::LLVMContext>();
TSCtx = std::make_unique<llvm::orc::ThreadSafeContext>(std::move(LLVMCtx));
IncrParser = std::make_unique<IncrementalParser>(*this, std::move(CI),
*TSCtx->getContext(), Err);
IncrParser = std::make_unique<IncrementalParser>(
*this, std::move(CI), *TSCtx->getContext(), ErrOut);
if (ErrOut)
return;

// Not all frontends support code-generation, e.g. ast-dump actions don't
if (IncrParser->getCodeGen()) {
if (llvm::Error Err = CreateExecutor()) {
ErrOut = joinErrors(std::move(ErrOut), std::move(Err));
return;
}

// Process the PTUs that came from initialization. For example -include will
// give us a header that's processed at initialization of the preprocessor.
for (PartialTranslationUnit &PTU : IncrParser->getPTUs())
if (llvm::Error Err = Execute(PTU)) {
ErrOut = joinErrors(std::move(ErrOut), std::move(Err));
return;
}
}
}

Interpreter::~Interpreter() {
Expand Down Expand Up @@ -382,25 +402,29 @@ createJITTargetMachineBuilder(const std::string &TT) {
return llvm::orc::JITTargetMachineBuilder(llvm::Triple(TT));
}

llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>>
Interpreter::CreateJITBuilder(CompilerInstance &CI) {
auto JTMB = createJITTargetMachineBuilder(CI.getTargetOpts().Triple);
if (!JTMB)
return JTMB.takeError();
return IncrementalExecutor::createDefaultJITBuilder(std::move(*JTMB));
}

llvm::Error Interpreter::CreateExecutor() {
if (IncrExecutor)
return llvm::make_error<llvm::StringError>("Operation failed. "
"Execution engine exists",
std::error_code());
llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>> JB =
CreateJITBuilder(*getCompilerInstance());
if (!JB)
return JB.takeError();
if (!IncrParser->getCodeGen())
return llvm::make_error<llvm::StringError>("Operation failed. "
"No code generator available",
std::error_code());
if (!JITBuilder) {
const std::string &TT = getCompilerInstance()->getTargetOpts().Triple;
auto JTMB = createJITTargetMachineBuilder(TT);
if (!JTMB)
return JTMB.takeError();
auto JB = IncrementalExecutor::createDefaultJITBuilder(std::move(*JTMB));
if (!JB)
return JB.takeError();
JITBuilder = std::move(*JB);
}

llvm::Error Err = llvm::Error::success();
auto Executor = std::make_unique<IncrementalExecutor>(*TSCtx, **JB, Err);
auto Executor =
std::make_unique<IncrementalExecutor>(*TSCtx, *JITBuilder, Err);
if (!Err)
IncrExecutor = std::move(Executor);

Expand Down
11 changes: 10 additions & 1 deletion clang/lib/Lex/Lexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2261,8 +2261,17 @@ bool Lexer::LexRawStringLiteral(Token &Result, const char *CurPtr,

unsigned PrefixLen = 0;

while (PrefixLen != 16 && isRawStringDelimBody(CurPtr[PrefixLen]))
while (PrefixLen != 16 && isRawStringDelimBody(CurPtr[PrefixLen])) {
++PrefixLen;
if (!isLexingRawMode() &&
llvm::is_contained({'$', '@', '`'}, CurPtr[PrefixLen])) {
const char *Pos = &CurPtr[PrefixLen];
Diag(Pos, LangOpts.CPlusPlus26
? diag::warn_cxx26_compat_raw_string_literal_character_set
: diag::ext_cxx26_raw_string_literal_character_set)
<< StringRef(Pos, 1);
}
}

// If the last character was not a '(', then we didn't lex a valid delimiter.
if (CurPtr[PrefixLen] != '(') {
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,11 @@ bool Parser::ParseAttributeArgumentList(
break;
}

if (Actions.DiagnoseUnexpandedParameterPack(Expr.get())) {
SawError = true;
break;
}

Exprs.push_back(Expr.get());

if (Tok.isNot(tok::comma))
Expand Down
19 changes: 10 additions & 9 deletions clang/lib/Parse/ParseOpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1347,11 +1347,13 @@ void Parser::ParseOpenACCCacheVarList() {
ParseOpenACCVarList(OpenACCClauseKind::Invalid);
}

Parser::OpenACCDirectiveParseInfo Parser::ParseOpenACCDirective() {
SourceLocation StartLoc = getCurToken().getLocation();
Parser::OpenACCDirectiveParseInfo
Parser::ParseOpenACCDirective() {
SourceLocation StartLoc = ConsumeAnnotationToken();
SourceLocation DirLoc = getCurToken().getLocation();
OpenACCDirectiveKind DirKind = ParseOpenACCDirectiveKind(*this);

getActions().OpenACC().ActOnConstruct(DirKind, StartLoc);
getActions().OpenACC().ActOnConstruct(DirKind, DirLoc);

// Once we've parsed the construct/directive name, some have additional
// specifiers that need to be taken care of. Atomic has an 'atomic-clause'
Expand Down Expand Up @@ -1390,7 +1392,7 @@ Parser::OpenACCDirectiveParseInfo Parser::ParseOpenACCDirective() {
break;
case OpenACCDirectiveKind::Wait:
// OpenACC has an optional paren-wrapped 'wait-argument'.
if (ParseOpenACCWaitArgument(StartLoc, /*IsDirective=*/true).Failed)
if (ParseOpenACCWaitArgument(DirLoc, /*IsDirective=*/true).Failed)
T.skipToEnd();
else
T.consumeClose();
Expand All @@ -1404,7 +1406,8 @@ Parser::OpenACCDirectiveParseInfo Parser::ParseOpenACCDirective() {
}

// Parses the list of clauses, if present, plus set up return value.
OpenACCDirectiveParseInfo ParseInfo{DirKind, StartLoc, SourceLocation{},
OpenACCDirectiveParseInfo ParseInfo{DirKind, StartLoc, DirLoc,
SourceLocation{},
ParseOpenACCClauseList(DirKind)};

assert(Tok.is(tok::annot_pragma_openacc_end) &&
Expand All @@ -1421,7 +1424,6 @@ Parser::DeclGroupPtrTy Parser::ParseOpenACCDirectiveDecl() {
assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token");

ParsingOpenACCDirectiveRAII DirScope(*this);
ConsumeAnnotationToken();

OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective();

Expand All @@ -1438,7 +1440,6 @@ StmtResult Parser::ParseOpenACCDirectiveStmt() {
assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token");

ParsingOpenACCDirectiveRAII DirScope(*this);
ConsumeAnnotationToken();

OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective();
if (getActions().OpenACC().ActOnStartStmtDirective(DirInfo.DirKind,
Expand All @@ -1456,6 +1457,6 @@ StmtResult Parser::ParseOpenACCDirectiveStmt() {
}

return getActions().OpenACC().ActOnEndStmtDirective(
DirInfo.DirKind, DirInfo.StartLoc, DirInfo.EndLoc, DirInfo.Clauses,
AssocStmt);
DirInfo.DirKind, DirInfo.StartLoc, DirInfo.DirLoc, DirInfo.EndLoc,
DirInfo.Clauses, AssocStmt);
}
1 change: 0 additions & 1 deletion clang/lib/Parse/ParseOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
#include "clang/Sema/SemaOpenMP.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/UniqueVector.h"
#include "llvm/Frontend/OpenMP/OMPAssume.h"
#include "llvm/Frontend/OpenMP/OMPContext.h"
#include <optional>
Expand Down
10 changes: 9 additions & 1 deletion clang/lib/Parse/ParseStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,15 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes(
auto IsStmtAttr = [](ParsedAttr &Attr) { return Attr.isStmtAttr(); };
bool AllAttrsAreStmtAttrs = llvm::all_of(CXX11Attrs, IsStmtAttr) &&
llvm::all_of(GNUAttrs, IsStmtAttr);
if (((GNUAttributeLoc.isValid() && !(HaveAttrs && AllAttrsAreStmtAttrs)) ||
// In C, the grammar production for statement (C23 6.8.1p1) does not allow
// for declarations, which is different from C++ (C++23 [stmt.pre]p1). So
// in C++, we always allow a declaration, but in C we need to check whether
// we're in a statement context that allows declarations. e.g., in C, the
// following is invalid: if (1) int x;
if ((getLangOpts().CPlusPlus || getLangOpts().MicrosoftExt ||
(StmtCtx & ParsedStmtContext::AllowDeclarationsInC) !=
ParsedStmtContext()) &&
((GNUAttributeLoc.isValid() && !(HaveAttrs && AllAttrsAreStmtAttrs)) ||
isDeclarationStatement())) {
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
DeclGroupPtrTy Decl;
Expand Down
17 changes: 12 additions & 5 deletions clang/lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3824,7 +3824,7 @@ bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall,
const PointerType *pointerType = PointerArg->getType()->getAs<PointerType>();
if (!pointerType) {
Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer)
<< PointerArg->getType() << PointerArg->getSourceRange();
<< PointerArg->getType() << 0 << PointerArg->getSourceRange();
return true;
}

Expand Down Expand Up @@ -3858,7 +3858,7 @@ bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall,
if (!ValType->isIntegerType() && !ValType->isAnyPointerType() &&
!ValType->isBlockPointerType() && !ValType->isFloatingType()) {
Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer_intfltptr)
<< PointerArg->getType() << PointerArg->getSourceRange();
<< PointerArg->getType() << 0 << PointerArg->getSourceRange();
return true;
}

Expand Down Expand Up @@ -6803,7 +6803,7 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
const PointerType *pointerType = Ptr->getType()->getAs<PointerType>();
if (!pointerType) {
Diag(ExprRange.getBegin(), diag::err_atomic_builtin_must_be_pointer)
<< Ptr->getType() << Ptr->getSourceRange();
<< Ptr->getType() << 0 << Ptr->getSourceRange();
return ExprError();
}

Expand Down Expand Up @@ -6832,6 +6832,13 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
}
}

// Pointer to object of size zero is not allowed.
if (Context.getTypeInfoInChars(AtomTy).Width.isZero()) {
Diag(ExprRange.getBegin(), diag::err_atomic_builtin_must_be_pointer)
<< Ptr->getType() << 1 << Ptr->getSourceRange();
return ExprError();
}

// For an arithmetic operation, the implied arithmetic must be well-formed.
if (Form == Arithmetic) {
// GCC does not enforce these rules for GNU atomics, but we do to help catch
Expand Down Expand Up @@ -7223,15 +7230,15 @@ ExprResult Sema::BuiltinAtomicOverloaded(ExprResult TheCallResult) {
const PointerType *pointerType = FirstArg->getType()->getAs<PointerType>();
if (!pointerType) {
Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer)
<< FirstArg->getType() << FirstArg->getSourceRange();
<< FirstArg->getType() << 0 << FirstArg->getSourceRange();
return ExprError();
}

QualType ValType = pointerType->getPointeeType();
if (!ValType->isIntegerType() && !ValType->isAnyPointerType() &&
!ValType->isBlockPointerType()) {
Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer_intptr)
<< FirstArg->getType() << FirstArg->getSourceRange();
<< FirstArg->getType() << 0 << FirstArg->getSourceRange();
return ExprError();
}

Expand Down
11 changes: 9 additions & 2 deletions clang/lib/Sema/SemaCodeComplete.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5692,8 +5692,15 @@ QualType getApproximateType(const Expr *E) {
}
}
if (const auto *UO = llvm::dyn_cast<UnaryOperator>(E)) {
if (UO->getOpcode() == UnaryOperatorKind::UO_Deref)
return UO->getSubExpr()->getType()->getPointeeType();
if (UO->getOpcode() == UnaryOperatorKind::UO_Deref) {
// We recurse into the subexpression because it could be of dependent
// type.
if (auto Pointee = getApproximateType(UO->getSubExpr())->getPointeeType();
!Pointee.isNull())
return Pointee;
// Our caller expects a non-null result, even though the SubType is
// supposed to have a pointee. Fall through to Unresolved anyway.
}
}
return Unresolved;
}
Expand Down
15 changes: 7 additions & 8 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -538,8 +538,9 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
} else if (AllowDeducedTemplate) {
if (auto *TD = getAsTypeTemplateDecl(IIDecl)) {
assert(!FoundUsingShadow || FoundUsingShadow->getTargetDecl() == TD);
TemplateName Template =
FoundUsingShadow ? TemplateName(FoundUsingShadow) : TemplateName(TD);
TemplateName Template = Context.getQualifiedTemplateName(
SS ? SS->getScopeRep() : nullptr, /*TemplateKeyword=*/false,
FoundUsingShadow ? TemplateName(FoundUsingShadow) : TemplateName(TD));
T = Context.getDeducedTemplateSpecializationType(Template, QualType(),
false);
// Don't wrap in a further UsingType.
Expand Down Expand Up @@ -1137,12 +1138,10 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS,
dyn_cast<UsingShadowDecl>(*Result.begin());
assert(!FoundUsingShadow ||
TD == cast<TemplateDecl>(FoundUsingShadow->getTargetDecl()));
Template =
FoundUsingShadow ? TemplateName(FoundUsingShadow) : TemplateName(TD);
if (SS.isNotEmpty())
Template = Context.getQualifiedTemplateName(SS.getScopeRep(),
/*TemplateKeyword=*/false,
Template);
Template = Context.getQualifiedTemplateName(
SS.getScopeRep(),
/*TemplateKeyword=*/false,
FoundUsingShadow ? TemplateName(FoundUsingShadow) : TemplateName(TD));
} else {
// All results were non-template functions. This is a function template
// name.
Expand Down
12 changes: 6 additions & 6 deletions clang/lib/Sema/SemaDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11547,12 +11547,12 @@ bool Sema::CheckDeductionGuideDeclarator(Declarator &D, QualType &R,
TemplateName SpecifiedName = RetTST.getTypePtr()->getTemplateName();
bool TemplateMatches =
Context.hasSameTemplateName(SpecifiedName, GuidedTemplate);
auto TKind = SpecifiedName.getKind();
// A Using TemplateName can't actually be valid (either it's qualified, or
// we're in the wrong scope). But we have diagnosed these problems
// already.
bool SimplyWritten = TKind == TemplateName::Template ||
TKind == TemplateName::UsingTemplate;

const QualifiedTemplateName *Qualifiers =
SpecifiedName.getAsQualifiedTemplateName();
assert(Qualifiers && "expected QualifiedTemplate");
bool SimplyWritten = !Qualifiers->hasTemplateKeyword() &&
Qualifiers->getQualifier() == nullptr;
if (SimplyWritten && TemplateMatches)
AcceptableReturnType = true;
else {
Expand Down
23 changes: 15 additions & 8 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3284,10 +3284,10 @@ ExprResult Sema::BuildDeclarationNameExpr(
return CreateRecoveryExpr(NameInfo.getBeginLoc(), NameInfo.getEndLoc(), {});
}

if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) {
if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) {
// Specifically diagnose references to class templates that are missing
// a template argument list.
diagnoseMissingTemplateArguments(TemplateName(Template), Loc);
diagnoseMissingTemplateArguments(SS, /*TemplateKeyword=*/false, TD, Loc);
return ExprError();
}

Expand Down Expand Up @@ -5506,6 +5506,15 @@ struct EnsureImmediateInvocationInDefaultArgs
// cause it to incorrectly point it to the outermost class
// in the case of nested struct initialization.
ExprResult TransformCXXThisExpr(CXXThisExpr *E) { return E; }

// Rewrite to source location to refer to the context in which they are used.
ExprResult TransformSourceLocExpr(SourceLocExpr *E) {
if (E->getParentContext() == SemaRef.CurContext)
return E;
return getDerived().RebuildSourceLocExpr(E->getIdentKind(), E->getType(),
E->getBeginLoc(), E->getEndLoc(),
SemaRef.CurContext);
}
};

ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
Expand Down Expand Up @@ -17223,8 +17232,7 @@ ExprResult Sema::TransformToPotentiallyEvaluated(Expr *E) {
TypeSourceInfo *Sema::TransformToPotentiallyEvaluated(TypeSourceInfo *TInfo) {
assert(isUnevaluatedContext() &&
"Should only transform unevaluated expressions");
ExprEvalContexts.back().Context =
ExprEvalContexts[ExprEvalContexts.size() - 2].Context;
ExprEvalContexts.back().Context = parentEvaluationContext().Context;
if (isUnevaluatedContext())
return TInfo;
return TransformToPE(*this).TransformType(TInfo);
Expand All @@ -17241,14 +17249,13 @@ Sema::PushExpressionEvaluationContext(
// discarded statements or immediate context are themselves
// a discarded statement or an immediate context, respectively.
ExprEvalContexts.back().InDiscardedStatement =
ExprEvalContexts[ExprEvalContexts.size() - 2]
.isDiscardedStatementContext();
parentEvaluationContext().isDiscardedStatementContext();

// C++23 [expr.const]/p15
// An expression or conversion is in an immediate function context if [...]
// it is a subexpression of a manifestly constant-evaluated expression or
// conversion.
const auto &Prev = ExprEvalContexts[ExprEvalContexts.size() - 2];
const auto &Prev = parentEvaluationContext();
ExprEvalContexts.back().InImmediateFunctionContext =
Prev.isImmediateFunctionContext() || Prev.isConstantEvaluated();

Expand Down Expand Up @@ -17693,7 +17700,7 @@ void Sema::PopExpressionEvaluationContext() {

// Append the collected materialized temporaries into previous context before
// exit if the previous also is a lifetime extending context.
auto &PrevRecord = ExprEvalContexts[ExprEvalContexts.size() - 2];
auto &PrevRecord = parentEvaluationContext();
if (getLangOpts().CPlusPlus23 && Rec.InLifetimeExtendingContext &&
PrevRecord.InLifetimeExtendingContext &&
!Rec.ForRangeLifetimeExtendTemps.empty()) {
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/Sema/SemaExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1444,10 +1444,10 @@ bool Sema::CheckCXXThisType(SourceLocation Loc, QualType Type) {
// category are defined within such member functions as they are within
// an implicit object member function).
DeclContext *DC = getFunctionLevelDeclContext();
if (const auto *Method = dyn_cast<CXXMethodDecl>(DC);
Method && Method->isExplicitObjectMemberFunction()) {
const auto *Method = dyn_cast<CXXMethodDecl>(DC);
if (Method && Method->isExplicitObjectMemberFunction()) {
Diag(Loc, diag::err_invalid_this_use) << 1;
} else if (isLambdaCallWithExplicitObjectParameter(CurContext)) {
} else if (Method && isLambdaCallWithExplicitObjectParameter(CurContext)) {
Diag(Loc, diag::err_invalid_this_use) << 1;
} else {
Diag(Loc, diag::err_invalid_this_use) << 0;
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Sema/SemaExprMember.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1194,7 +1194,8 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,

if (VarTemplateDecl *VarTempl = dyn_cast<VarTemplateDecl>(MemberDecl)) {
if (!TemplateArgs) {
diagnoseMissingTemplateArguments(TemplateName(VarTempl), MemberLoc);
diagnoseMissingTemplateArguments(
SS, /*TemplateKeyword=*/TemplateKWLoc.isValid(), VarTempl, MemberLoc);
return ExprError();
}

Expand Down
10 changes: 10 additions & 0 deletions clang/lib/Sema/SemaLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5897,6 +5897,16 @@ void Sema::diagnoseTypo(const TypoCorrection &Correction,

NamedDecl *ChosenDecl =
Correction.isKeyword() ? nullptr : Correction.getFoundDecl();

// For builtin functions which aren't declared anywhere in source,
// don't emit the "declared here" note.
if (const auto *FD = dyn_cast_if_present<FunctionDecl>(ChosenDecl);
FD && FD->getBuiltinID() &&
PrevNote.getDiagID() == diag::note_previous_decl &&
Correction.getCorrectionRange().getBegin() == FD->getBeginLoc()) {
ChosenDecl = nullptr;
}

if (PrevNote.getDiagID() && ChosenDecl)
Diag(ChosenDecl->getLocation(), PrevNote)
<< CorrectedQuotedStr << (ErrorRecovery ? FixItHint() : FixTypo);
Expand Down
7 changes: 4 additions & 3 deletions clang/lib/Sema/SemaOpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -844,7 +844,7 @@ ExprResult SemaOpenACC::CheckReductionVar(Expr *VarExpr) {
}

void SemaOpenACC::ActOnConstruct(OpenACCDirectiveKind K,
SourceLocation StartLoc) {
SourceLocation DirLoc) {
switch (K) {
case OpenACCDirectiveKind::Invalid:
// Nothing to do here, an invalid kind has nothing we can check here. We
Expand All @@ -859,7 +859,7 @@ void SemaOpenACC::ActOnConstruct(OpenACCDirectiveKind K,
// here as these constructs do not take any arguments.
break;
default:
Diag(StartLoc, diag::warn_acc_construct_unimplemented) << K;
Diag(DirLoc, diag::warn_acc_construct_unimplemented) << K;
break;
}
}
Expand Down Expand Up @@ -1265,6 +1265,7 @@ bool SemaOpenACC::ActOnStartStmtDirective(OpenACCDirectiveKind K,

StmtResult SemaOpenACC::ActOnEndStmtDirective(OpenACCDirectiveKind K,
SourceLocation StartLoc,
SourceLocation DirLoc,
SourceLocation EndLoc,
ArrayRef<OpenACCClause *> Clauses,
StmtResult AssocStmt) {
Expand All @@ -1278,7 +1279,7 @@ StmtResult SemaOpenACC::ActOnEndStmtDirective(OpenACCDirectiveKind K,
case OpenACCDirectiveKind::Kernels:
// TODO OpenACC: Add clauses to the construct here.
return OpenACCComputeConstruct::Create(
getASTContext(), K, StartLoc, EndLoc, Clauses,
getASTContext(), K, StartLoc, DirLoc, EndLoc, Clauses,
AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
}
llvm_unreachable("Unhandled case in directive handling?");
Expand Down
17 changes: 13 additions & 4 deletions clang/lib/Sema/SemaOverload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DependenceFlags.h"
Expand Down Expand Up @@ -1481,7 +1482,7 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New,
}

if (OldMethod && NewMethod && !OldMethod->isStatic() &&
!OldMethod->isStatic()) {
!NewMethod->isStatic()) {
bool HaveCorrespondingObjectParameters = [&](const CXXMethodDecl *Old,
const CXXMethodDecl *New) {
auto NewObjectType = New->getFunctionObjectParameterReferenceType();
Expand Down Expand Up @@ -11301,8 +11302,16 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
Expr *FromExpr = Conv.Bad.FromExpr;
QualType FromTy = Conv.Bad.getFromType();
QualType ToTy = Conv.Bad.getToType();
SourceRange ToParamRange =
!isObjectArgument ? Fn->getParamDecl(I)->getSourceRange() : SourceRange();
SourceRange ToParamRange;

// FIXME: In presence of parameter packs we can't determine parameter range
// reliably, as we don't have access to instantiation.
bool HasParamPack =
llvm::any_of(Fn->parameters().take_front(I), [](const ParmVarDecl *Parm) {
return Parm->isParameterPack();
});
if (!isObjectArgument && !HasParamPack)
ToParamRange = Fn->getParamDecl(I)->getSourceRange();

if (FromTy == S.Context.OverloadTy) {
assert(FromExpr && "overload set argument came from implicit argument?");
Expand Down Expand Up @@ -14354,7 +14363,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
if (Fn.isInvalid())
return ExprError();
return CXXOperatorCallExpr::Create(Context, Op, Fn.get(), ArgsArray,
Context.DependentTy, VK, OpLoc,
Context.DependentTy, VK_PRValue, OpLoc,
CurFPFeatureOverrides());
}

Expand Down
6 changes: 2 additions & 4 deletions clang/lib/Sema/SemaStmtAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ bool Sema::CheckAlwaysInlineAttr(const Stmt *OrigSt, const Stmt *CurSt,
static Attr *handleNoInlineAttr(Sema &S, Stmt *St, const ParsedAttr &A,
SourceRange Range) {
NoInlineAttr NIA(S.Context, A);
if (!NIA.isClangNoInline()) {
if (!NIA.isStmtNoInline()) {
S.Diag(St->getBeginLoc(), diag::warn_function_attribute_ignored_in_stmt)
<< "[[clang::noinline]]";
return nullptr;
Expand Down Expand Up @@ -684,10 +684,8 @@ ExprResult Sema::ActOnCXXAssumeAttr(Stmt *St, const ParsedAttr &A,
}

if (!getLangOpts().CPlusPlus23 &&
A.getSyntax() == AttributeCommonInfo::AS_CXX11) {
llvm::dbgs() << "Syntax: " << int(A.getSyntax()) << "\n";
A.getSyntax() == AttributeCommonInfo::AS_CXX11)
Diag(A.getLoc(), diag::ext_cxx23_attr) << A << Range;
}

return Assumption;
}
Expand Down
25 changes: 17 additions & 8 deletions clang/lib/Sema/SemaTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
Template =
FoundUsingShadow ? TemplateName(FoundUsingShadow) : TemplateName(TD);
assert(!FoundUsingShadow || FoundUsingShadow->getTargetDecl() == TD);
if (SS.isSet() && !SS.isInvalid()) {
if (!SS.isInvalid()) {
NestedNameSpecifier *Qualifier = SS.getScopeRep();
Template = Context.getQualifiedTemplateName(Qualifier, hasTemplateKeyword,
Template);
Expand Down Expand Up @@ -342,8 +342,11 @@ bool Sema::isDeductionGuideName(Scope *S, const IdentifierInfo &Name,
if (!TD || !getAsTypeTemplateDecl(TD))
return false;

if (Template)
*Template = TemplateTy::make(TemplateName(TD));
if (Template) {
TemplateName Name = Context.getQualifiedTemplateName(
SS.getScopeRep(), /*TemplateKeyword=*/false, TemplateName(TD));
*Template = TemplateTy::make(Name);
}
return true;
}

Expand Down Expand Up @@ -983,10 +986,6 @@ ParsedTemplateArgument Sema::ActOnTemplateTypeArgument(TypeResult ParsedType) {

if (auto DTST = TL.getAs<DeducedTemplateSpecializationTypeLoc>()) {
TemplateName Name = DTST.getTypePtr()->getTemplateName();
if (SS.isSet())
Name = Context.getQualifiedTemplateName(SS.getScopeRep(),
/*HasTemplateKeyword=*/false,
Name);
ParsedTemplateArgument Result(SS, TemplateTy::make(Name),
DTST.getTemplateNameLoc());
if (EllipsisLoc.isValid())
Expand Down Expand Up @@ -5621,6 +5620,15 @@ void Sema::diagnoseMissingTemplateArguments(TemplateName Name,
}
}

void Sema::diagnoseMissingTemplateArguments(const CXXScopeSpec &SS,
bool TemplateKeyword,
TemplateDecl *TD,
SourceLocation Loc) {
TemplateName Name = Context.getQualifiedTemplateName(
SS.getScopeRep(), TemplateKeyword, TemplateName(TD));
diagnoseMissingTemplateArguments(Name, Loc);
}

ExprResult
Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
Expand Down Expand Up @@ -5691,7 +5699,8 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
// Non-function templates require a template argument list.
if (auto *TD = R.getAsSingle<TemplateDecl>()) {
if (!TemplateArgs && !isa<FunctionTemplateDecl>(TD)) {
diagnoseMissingTemplateArguments(TemplateName(TD), R.getNameLoc());
diagnoseMissingTemplateArguments(
SS, /*TemplateKeyword=*/TemplateKWLoc.isValid(), TD, R.getNameLoc());
return ExprError();
}
}
Expand Down
62 changes: 47 additions & 15 deletions clang/lib/Sema/SemaTemplateDeduction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,6 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
// arguments as defaults.
if (auto *TempArg = dyn_cast_or_null<TemplateTemplateParmDecl>(
Arg.getAsTemplateDecl())) {
assert(Arg.getKind() == TemplateName::Template);
assert(!TempArg->isExpandedParameterPack());

TemplateParameterList *As = TempArg->getTemplateParameters();
Expand Down Expand Up @@ -658,6 +657,18 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
/// \returns the result of template argument deduction so far. Note that a
/// "success" result means that template argument deduction has not yet failed,
/// but it may still fail, later, for other reasons.

static const TemplateSpecializationType *getLastTemplateSpecType(QualType QT) {
for (const Type *T = QT.getTypePtr(); /**/; /**/) {
const TemplateSpecializationType *TST =
T->getAs<TemplateSpecializationType>();
assert(TST && "Expected a TemplateSpecializationType");
if (!TST->isSugared())
return TST;
T = TST->desugar().getTypePtr();
}
}

static TemplateDeductionResult
DeduceTemplateSpecArguments(Sema &S, TemplateParameterList *TemplateParams,
const QualType P, QualType A,
Expand All @@ -666,26 +677,35 @@ DeduceTemplateSpecArguments(Sema &S, TemplateParameterList *TemplateParams,
QualType UP = P;
if (const auto *IP = P->getAs<InjectedClassNameType>())
UP = IP->getInjectedSpecializationType();
// FIXME: Try to preserve type sugar here, which is hard
// because of the unresolved template arguments.
const auto *TP = UP.getCanonicalType()->castAs<TemplateSpecializationType>();

assert(isa<TemplateSpecializationType>(UP.getCanonicalType()));
const TemplateSpecializationType *TP = ::getLastTemplateSpecType(UP);
TemplateName TNP = TP->getTemplateName();

// If the parameter is an alias template, there is nothing to deduce.
if (const auto *TD = TNP.getAsTemplateDecl(); TD && TD->isTypeAlias())
return TemplateDeductionResult::Success;

ArrayRef<TemplateArgument> PResolved = TP->template_arguments();
// FIXME: To preserve sugar, the TST needs to carry sugared resolved
// arguments.
ArrayRef<TemplateArgument> PResolved =
TP->getCanonicalTypeInternal()
->castAs<TemplateSpecializationType>()
->template_arguments();

QualType UA = A;
std::optional<NestedNameSpecifier *> NNS;
// Treat an injected-class-name as its underlying template-id.
if (const auto *Injected = A->getAs<InjectedClassNameType>())
if (const auto *Elaborated = A->getAs<ElaboratedType>()) {
NNS = Elaborated->getQualifier();
} else if (const auto *Injected = A->getAs<InjectedClassNameType>()) {
UA = Injected->getInjectedSpecializationType();
NNS = nullptr;
}

// Check whether the template argument is a dependent template-id.
// FIXME: Should not lose sugar here.
if (const auto *SA =
dyn_cast<TemplateSpecializationType>(UA.getCanonicalType())) {
if (isa<TemplateSpecializationType>(UA.getCanonicalType())) {
const TemplateSpecializationType *SA = ::getLastTemplateSpecType(UA);
TemplateName TNA = SA->getTemplateName();

// If the argument is an alias template, there is nothing to deduce.
Expand All @@ -698,11 +718,19 @@ DeduceTemplateSpecArguments(Sema &S, TemplateParameterList *TemplateParams,
SA->template_arguments(), Deduced);
Result != TemplateDeductionResult::Success)
return Result;

// FIXME: To preserve sugar, the TST needs to carry sugared resolved
// arguments.
ArrayRef<TemplateArgument> AResolved =
SA->getCanonicalTypeInternal()
->castAs<TemplateSpecializationType>()
->template_arguments();

// Perform template argument deduction on each template
// argument. Ignore any missing/extra arguments, since they could be
// filled in by default arguments.
return DeduceTemplateArguments(S, TemplateParams, PResolved,
SA->template_arguments(), Info, Deduced,
return DeduceTemplateArguments(S, TemplateParams, PResolved, AResolved,
Info, Deduced,
/*NumberOfArgumentsMustMatch=*/false);
}

Expand All @@ -718,11 +746,15 @@ DeduceTemplateSpecArguments(Sema &S, TemplateParameterList *TemplateParams,
return TemplateDeductionResult::NonDeducedMismatch;
}

TemplateName TNA = TemplateName(SA->getSpecializedTemplate());
if (NNS)
TNA = S.Context.getQualifiedTemplateName(
*NNS, false, TemplateName(SA->getSpecializedTemplate()));

// Perform template argument deduction for the template name.
if (auto Result = DeduceTemplateArguments(
S, TemplateParams, TP->getTemplateName(),
TemplateName(SA->getSpecializedTemplate()), Info,
SA->getTemplateArgs().asArray(), Deduced);
if (auto Result =
DeduceTemplateArguments(S, TemplateParams, TNP, TNA, Info,
SA->getTemplateArgs().asArray(), Deduced);
Result != TemplateDeductionResult::Success)
return Result;

Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Sema/SemaTemplateVariadic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ namespace {

bool shouldWalkTypesOfTypeLocs() const { return false; }

// We need this so we can find e.g. attributes on lambdas.
bool shouldVisitImplicitCode() const { return true; }

//------------------------------------------------------------------------
// Recording occurrences of (unexpanded) parameter packs.
//------------------------------------------------------------------------
Expand Down
14 changes: 9 additions & 5 deletions clang/lib/Sema/SemaType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6005,12 +6005,16 @@ namespace {
DeclarationNameInfo DNI = DeclarationNameInfo(
TL.getTypePtr()->getTypeConstraintConcept()->getDeclName(),
TemplateId->TemplateNameLoc);
auto TN = TemplateId->Template.get();

NamedDecl *FoundDecl;
if (auto TN = TemplateId->Template.get();
UsingShadowDecl *USD = TN.getAsUsingShadowDecl())
FoundDecl = cast<NamedDecl>(USD);
else
FoundDecl = cast_if_present<NamedDecl>(TN.getAsTemplateDecl());

auto *CR = ConceptReference::Create(
Context, NNS, TemplateId->TemplateKWLoc, DNI,
/*FoundDecl=*/TN.getKind() == TemplateName::NameKind::UsingTemplate
? cast<NamedDecl>(TN.getAsUsingShadowDecl())
: cast_if_present<NamedDecl>(TN.getAsTemplateDecl()),
Context, NNS, TemplateId->TemplateKWLoc, DNI, FoundDecl,
/*NamedDecl=*/TL.getTypePtr()->getTypeConstraintConcept(),
ASTTemplateArgumentListInfo::Create(Context, TemplateArgsInfo));
TL.setConceptReference(CR);
Expand Down
17 changes: 8 additions & 9 deletions clang/lib/Sema/TreeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -4033,11 +4033,12 @@ class TreeTransform {

StmtResult RebuildOpenACCComputeConstruct(OpenACCDirectiveKind K,
SourceLocation BeginLoc,
SourceLocation DirLoc,
SourceLocation EndLoc,
ArrayRef<OpenACCClause *> Clauses,
StmtResult StrBlock) {
return getSema().OpenACC().ActOnEndStmtDirective(K, BeginLoc, EndLoc,
Clauses, StrBlock);
return getSema().OpenACC().ActOnEndStmtDirective(K, BeginLoc, DirLoc,
EndLoc, Clauses, StrBlock);
}

private:
Expand Down Expand Up @@ -4604,18 +4605,16 @@ TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS,
ObjectType, AllowInjectedClassName);
}

// FIXME: Try to preserve more of the TemplateName.
if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
TemplateDecl *TransTemplate
= cast_or_null<TemplateDecl>(getDerived().TransformDecl(NameLoc,
Template));
if (!TransTemplate)
return TemplateName();

if (!getDerived().AlwaysRebuild() &&
TransTemplate == Template)
return Name;

return TemplateName(TransTemplate);
return getDerived().RebuildTemplateName(SS, /*TemplateKeyword=*/false,
TransTemplate);
}

if (SubstTemplateTemplateParmPackStorage *SubstPack
Expand Down Expand Up @@ -11559,8 +11558,8 @@ StmtResult TreeTransform<Derived>::TransformOpenACCComputeConstruct(
getSema().OpenACC().ActOnAssociatedStmt(C->getDirectiveKind(), StrBlock);

return getDerived().RebuildOpenACCComputeConstruct(
C->getDirectiveKind(), C->getBeginLoc(), C->getEndLoc(),
TransformedClauses, StrBlock);
C->getDirectiveKind(), C->getBeginLoc(), C->getDirectiveLoc(),
C->getEndLoc(), TransformedClauses, StrBlock);
}

//===----------------------------------------------------------------------===//
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/Serialization/ASTReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1264,7 +1264,7 @@ bool ASTReader::ReadLexicalDeclContextStorage(ModuleFile &M,
if (!Lex.first) {
Lex = std::make_pair(
&M, llvm::ArrayRef(
reinterpret_cast<const unalighed_decl_id_t *>(Blob.data()),
reinterpret_cast<const unaligned_decl_id_t *>(Blob.data()),
Blob.size() / sizeof(DeclID)));
}
DC->setHasExternalLexicalStorage(true);
Expand Down Expand Up @@ -3401,7 +3401,7 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F,
case TU_UPDATE_LEXICAL: {
DeclContext *TU = ContextObj->getTranslationUnitDecl();
LexicalContents Contents(
reinterpret_cast<const unalighed_decl_id_t *>(Blob.data()),
reinterpret_cast<const unaligned_decl_id_t *>(Blob.data()),
static_cast<unsigned int>(Blob.size() / sizeof(DeclID)));
TULexicalDecls.push_back(std::make_pair(&F, Contents));
TU->setHasExternalLexicalStorage(true);
Expand Down Expand Up @@ -4059,7 +4059,7 @@ void ASTReader::ReadModuleOffsetMap(ModuleFile &F) const {
RemapBuilder DeclRemap(F.DeclRemap);
RemapBuilder TypeRemap(F.TypeRemap);

auto &ImportedModuleVector = F.DependentModules;
auto &ImportedModuleVector = F.TransitiveImports;
assert(ImportedModuleVector.empty());

while (Data < DataEnd) {
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Serialization/ASTReaderStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2797,6 +2797,7 @@ void ASTStmtReader::VisitOpenACCConstructStmt(OpenACCConstructStmt *S) {
(void)Record.readInt();
S->Kind = Record.readEnum<OpenACCDirectiveKind>();
S->Range = Record.readSourceRange();
S->DirectiveLoc = Record.readSourceLocation();
Record.readOpenACCClauseList(S->Clauses);
}

Expand Down
28 changes: 19 additions & 9 deletions clang/lib/Serialization/ASTWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1049,6 +1049,7 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(DECL_UNRESOLVED_USING_VALUE);
RECORD(DECL_UNRESOLVED_USING_TYPENAME);
RECORD(DECL_LINKAGE_SPEC);
RECORD(DECL_EXPORT);
RECORD(DECL_CXX_RECORD);
RECORD(DECL_CXX_METHOD);
RECORD(DECL_CXX_CONSTRUCTOR);
Expand Down Expand Up @@ -5037,6 +5038,14 @@ void ASTWriter::PrepareWritingSpecialDecls(Sema &SemaRef) {
continue;
}

// If we're writing C++ named modules, don't emit declarations which are
// not from modules by default. They may be built in declarations (be
// handled above) or implcit declarations (see the implementation of
// `Sema::Initialize()` for example).
if (isWritingStdCXXNamedModules() && !D->getOwningModule() &&
D->isImplicit())
continue;

GetDeclRef(D);
}

Expand Down Expand Up @@ -6197,8 +6206,9 @@ bool ASTWriter::wasDeclEmitted(const Decl *D) const {
return true;

bool Emitted = DeclIDs.contains(D);
assert((Emitted || GeneratingReducedBMI) &&
"The declaration can only be omitted in reduced BMI.");
assert((Emitted || (!D->getOwningModule() && isWritingStdCXXNamedModules()) ||
GeneratingReducedBMI) &&
"The declaration within modules can only be omitted in reduced BMI.");
return Emitted;
}

Expand Down Expand Up @@ -7825,15 +7835,15 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {
case OpenACCClauseKind::If: {
const auto *IC = cast<OpenACCIfClause>(C);
writeSourceLocation(IC->getLParenLoc());
writeStmtRef(IC->getConditionExpr());
AddStmt(const_cast<Expr*>(IC->getConditionExpr()));
return;
}
case OpenACCClauseKind::Self: {
const auto *SC = cast<OpenACCSelfClause>(C);
writeSourceLocation(SC->getLParenLoc());
writeBool(SC->hasConditionExpr());
if (SC->hasConditionExpr())
writeStmtRef(SC->getConditionExpr());
AddStmt(const_cast<Expr*>(SC->getConditionExpr()));
return;
}
case OpenACCClauseKind::NumGangs: {
Expand All @@ -7847,13 +7857,13 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {
case OpenACCClauseKind::NumWorkers: {
const auto *NWC = cast<OpenACCNumWorkersClause>(C);
writeSourceLocation(NWC->getLParenLoc());
writeStmtRef(NWC->getIntExpr());
AddStmt(const_cast<Expr*>(NWC->getIntExpr()));
return;
}
case OpenACCClauseKind::VectorLength: {
const auto *NWC = cast<OpenACCVectorLengthClause>(C);
writeSourceLocation(NWC->getLParenLoc());
writeStmtRef(NWC->getIntExpr());
AddStmt(const_cast<Expr*>(NWC->getIntExpr()));
return;
}
case OpenACCClauseKind::Private: {
Expand Down Expand Up @@ -7932,15 +7942,15 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {
writeSourceLocation(AC->getLParenLoc());
writeBool(AC->hasIntExpr());
if (AC->hasIntExpr())
writeStmtRef(AC->getIntExpr());
AddStmt(const_cast<Expr*>(AC->getIntExpr()));
return;
}
case OpenACCClauseKind::Wait: {
const auto *WC = cast<OpenACCWaitClause>(C);
writeSourceLocation(WC->getLParenLoc());
writeBool(WC->getDevNumExpr());
if (const Expr *DNE = WC->getDevNumExpr())
writeStmtRef(DNE);
if (Expr *DNE = WC->getDevNumExpr())
AddStmt(DNE);
writeSourceLocation(WC->getQueuesLoc());

writeOpenACCIntExprList(WC->getQueueIdExprs());
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Serialization/ASTWriterStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2847,6 +2847,7 @@ void ASTStmtWriter::VisitOpenACCConstructStmt(OpenACCConstructStmt *S) {
Record.push_back(S->clauses().size());
Record.writeEnum(S->Kind);
Record.AddSourceRange(S->Range);
Record.AddSourceLocation(S->DirectiveLoc);
Record.writeOpenACCClauseList(S->clauses());
}

Expand Down
9 changes: 7 additions & 2 deletions clang/lib/StaticAnalyzer/Checkers/PutenvStackArrayChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,14 @@ void PutenvStackArrayChecker::checkPostCall(const CallEvent &Call,

SVal ArgV = Call.getArgSVal(0);
const Expr *ArgExpr = Call.getArgExpr(0);
const MemSpaceRegion *MSR = ArgV.getAsRegion()->getMemorySpace();

if (!isa<StackSpaceRegion>(MSR))
const auto *SSR =
dyn_cast<StackSpaceRegion>(ArgV.getAsRegion()->getMemorySpace());
if (!SSR)
return;
const auto *StackFrameFuncD =
dyn_cast_or_null<FunctionDecl>(SSR->getStackFrame()->getDecl());
if (StackFrameFuncD && StackFrameFuncD->isMain())
return;

StringRef ErrorMsg = "The 'putenv' function should not be called with "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class DerefFuncDeleteExprVisitor
std::optional<bool> HasSpecializedDelete(CXXMethodDecl *Decl) {
if (auto *Body = Decl->getBody())
return VisitBody(Body);
if (auto *Tmpl = Decl->getTemplateInstantiationPattern())
if (Decl->getTemplateInstantiationPattern())
return std::nullopt; // Indeterminate. There was no concrete instance.
return false;
}
Expand Down
6 changes: 6 additions & 0 deletions clang/test/AST/Interp/functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -623,3 +623,9 @@ namespace FuncPtrParam {
*a; // both-warning {{expression result unused}}
}
}

namespace {
void f() noexcept;
void (&r)() = f;
void (&cond3)() = r;
}
5 changes: 5 additions & 0 deletions clang/test/AST/Interp/objc.mm
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,8 @@ @interface A {
static_assert(a, ""); // both-error {{static assertion expression is not an integral constant expression}}
}
@end

@interface NSString
@end
constexpr NSString *t0 = @"abc";
constexpr NSString *t1 = @("abc");
13 changes: 13 additions & 0 deletions clang/test/AST/Interp/records.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1467,3 +1467,16 @@ namespace IgnoredCtorWithZeroInit {
return (S(), true);
}
}

#if __cplusplus >= 202002L
namespace VirtOperator {
/// This used to crash because it's a virtual CXXOperatorCallExpr.
struct B {
virtual constexpr bool operator==(const B&) const { return true; }
};
struct D : B {
constexpr bool operator==(const B&) const override{ return false; } // both-note {{operator}}
};
constexpr bool cmp_base_derived = D() == D(); // both-warning {{ambiguous}}
}
#endif
6 changes: 3 additions & 3 deletions clang/test/AST/ast-dump-ctad-alias.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,17 @@ Out2<double>::AInner t(1.0);
// CHECK: | `-FunctionTemplateDecl {{.*}} <deduction guide for AInner>
// CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} typename depth 0 index 0 Y
// CHECK-NEXT: | |-BinaryOperator {{.*}} '<dependent type>' '&&'
// CHECK-NEXT: | | |-UnresolvedLookupExpr {{.*}} '<dependent type>' lvalue (no ADL) = 'Concept'
// CHECK-NEXT: | | |-UnresolvedLookupExpr {{.*}} '<dependent type>' lvalue (no ADL) = 'Concept'
// CHECK-NEXT: | | | |-TemplateArgument type 'int'
// CHECK-NEXT: | | | | `-BuiltinType {{.*}} 'int'
// CHECK-NEXT: | | | `-TemplateArgument type 'type-parameter-1-0'
// CHECK-NEXT: | | | `-TemplateTypeParmType {{.*}} 'type-parameter-1-0' dependent depth 1 index 0
// CHECK-NEXT: | | `-TypeTraitExpr {{.*}} 'bool' __is_deducible
// CHECK-NEXT: | | |-DeducedTemplateSpecializationType {{.*}} 'AInner' dependent
// CHECK-NEXT: | | |-DeducedTemplateSpecializationType {{.*}} 'Out2<double>::AInner' dependent
// CHECK-NEXT: | | `-ElaboratedType {{.*}} 'Inner<type-parameter-1-0>' sugar dependent
// CHECK-NEXT: | | `-TemplateSpecializationType {{.*}} 'Inner<type-parameter-1-0>' dependent Inner
// CHECK-NEXT: | | `-TemplateArgument type 'type-parameter-1-0'
// CHECK-NEXT: | | `-SubstTemplateTypeParmType {{.*}} 'type-parameter-1-0'
// CHECK-NEXT: | | `-SubstTemplateTypeParmType {{.*}} 'type-parameter-1-0'
// CHECK-NEXT: | | |-FunctionTemplate {{.*}} '<deduction guide for Inner>'
// CHECK-NEXT: | | `-TemplateTypeParmType {{.*}} 'type-parameter-1-0' dependent depth 1 index 0
// CHECK-NEXT: | |-CXXDeductionGuideDecl {{.*}} <deduction guide for AInner> 'auto (type-parameter-0-0) -> Inner<type-parameter-0-0>'
Expand Down
25 changes: 14 additions & 11 deletions clang/test/AST/ast-dump-decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -459,21 +459,23 @@ namespace testClassTemplateDecl {

// CHECK: ClassTemplateDecl 0x{{.+}} <{{.+}}:[[@LINE-148]]:3, col:31> col:31 TestTemplateDefaultNonType{{$}}
// CHECK-NEXT: |-NonTypeTemplateParmDecl 0x{{.+}} <col:12, col:20> col:16 'int' depth 0 index 0 I{{$}}
// CHECK-NEXT: | `-TemplateArgument <col:20> expr{{$}}
// CHECK-NEXT: | `-TemplateArgument <col:20> expr '42'{{$}}
// CHECK-NEXT: | `-IntegerLiteral 0x{{.+}} <col:20> 'int' 42{{$}}
// CHECK-NEXT: `-CXXRecordDecl 0x{{.+}} <col:24, col:31> col:31 struct TestTemplateDefaultNonType{{$}}

// CHECK: ClassTemplateDecl 0x{{.+}} <{{.+}}:{{.*}}:3, col:68> col:68 TestTemplateTemplateDefaultType{{$}}
// CHECK-NEXT: |-TemplateTemplateParmDecl 0x{{.+}} <col:12, col:42> col:37 depth 0 index 0 TT{{$}}
// CHECK-NEXT: | |-TemplateTypeParmDecl 0x{{.+}} <col:21> col:29 typename depth 1 index 0{{$}}
// CHECK-NEXT: | `-TemplateArgument <col:42> template TestClassTemplate{{$}}
// CHECK-NEXT: `-CXXRecordDecl 0x{{.+}} <col:61, col:68> col:68 struct TestTemplateTemplateDefaultType{{$}}
// CHECK-NEXT: | `-TemplateArgument <col:42> template 'TestClassTemplate':'testClassTemplateDecl::TestClassTemplate' qualified{{$}}
// CHECK-NEXT: | `-ClassTemplateDecl 0x{{.+}} <line:{{.+}}:3, line:{{.+}}:3> line:{{.+}}:30 TestClassTemplate{{$}}
// CHECK-NEXT: `-CXXRecordDecl 0x{{.+}} <line:{{.*}}:61, col:68> col:68 struct TestTemplateTemplateDefaultType{{$}}

// CHECK: ClassTemplateDecl 0x{{.+}} prev 0x{{.+}} <{{.+}}:{{.*}}:3, col:82> col:48 TestTemplateTemplateDefaultType{{$}}
// CHECK-NEXT: |-TemplateTemplateParmDecl 0x{{.+}} <col:12, col:37> col:37 depth 0 index 0 TT{{$}}
// CHECK-NEXT: | |-TemplateTypeParmDecl 0x{{.+}} <col:21> col:29 typename depth 1 index 0{{$}}
// CHECK-NEXT: | `-TemplateArgument <line:{{.*}}:42> template TestClassTemplate{{$}}
// CHECK-NEXT: | `-inherited from TemplateTemplateParm 0x{{.+}} 'TT'{{$}}
// CHECK-NEXT: | `-TemplateArgument <line:{{.*}}:42> template 'TestClassTemplate':'testClassTemplateDecl::TestClassTemplate' qualified{{$}}
// CHECK-NEXT: | |-inherited from TemplateTemplateParm 0x{{.+}} 'TT'{{$}}
// CHECK-NEXT: | `-ClassTemplateDecl 0x{{.+}} <line:{{.+}}:3, line:{{.+}}:3> line:{{.+}}:30 TestClassTemplate
// CHECK-NEXT: `-CXXRecordDecl 0x{{.+}} prev 0x{{.+}} <line:{{.*}}:41, col:82> col:48 struct TestTemplateTemplateDefaultType definition{{$}}
// CHECK-NEXT: |-DefinitionData empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init{{$}}
// CHECK-NEXT: | |-DefaultConstructor exists trivial constexpr needs_implicit defaulted_is_constexpr{{$}}
Expand Down Expand Up @@ -683,7 +685,8 @@ namespace TestTemplateTemplateParmDecl {
// CHECK: FunctionTemplateDecl
// CHECK-NEXT: TemplateTemplateParmDecl{{.*}} T
// CHECK-NEXT: TemplateTypeParmDecl{{.*}} typename
// CHECK-NEXT: TemplateArgument{{.*}} template A
// CHECK-NEXT: TemplateArgument{{.*}} template 'A':'TestTemplateTemplateParmDecl::A' qualified{{$}}
// CHECK-NEXT: ClassTemplateDecl {{.*}} A
// CHECK-NEXT: TemplateTemplateParmDecl{{.*}} ... U
// CHECK-NEXT: TemplateTypeParmDecl{{.*}} typename

Expand All @@ -710,12 +713,12 @@ namespace TestTemplateArgument {
template<int> class testIntegral { };
template class testIntegral<1>;
// CHECK: ClassTemplateSpecializationDecl{{.*}} class testIntegral
// CHECK: TemplateArgument{{.*}} integral 1
// CHECK: TemplateArgument{{.*}} integral '1'

template<template<typename> class> class testTemplate { };
template class testTemplate<A>;
// CHECK: ClassTemplateSpecializationDecl{{.*}} class testTemplate
// CHECK: TemplateArgument{{.*}} A
// CHECK: TemplateArgument{{.*}} 'TestTemplateArgument::A'{{$}}

template<template<typename> class ...T> class C {
B<T...> testTemplateExpansion;
Expand All @@ -731,10 +734,10 @@ namespace TestTemplateArgument {
template<int, int ...> class testPack { };
template class testPack<0, 1, 2>;
// CHECK: ClassTemplateSpecializationDecl{{.*}} class testPack
// CHECK: TemplateArgument{{.*}} integral 0
// CHECK: TemplateArgument{{.*}} integral '0'
// CHECK-NEXT: TemplateArgument{{.*}} pack
// CHECK-NEXT: TemplateArgument{{.*}} integral 1
// CHECK-NEXT: TemplateArgument{{.*}} integral 2
// CHECK-NEXT: TemplateArgument{{.*}} integral '1'
// CHECK-NEXT: TemplateArgument{{.*}} integral '2'
}

namespace testUsingDecl {
Expand Down
2 changes: 1 addition & 1 deletion clang/test/AST/ast-dump-expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ void PostfixExpressions(S a, S *p, U<int> *r) {
r->template U<int>::~U();
// CHECK: CXXMemberCallExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:26> 'void'
// CHECK-NEXT: MemberExpr 0x{{[^ ]*}} <col:3, col:24> '<bound member function type>' ->~U 0x{{[^ ]*}}
// CHECK-NEXT: NestedNameSpecifier TypeSpecWithTemplate 'U<int>'
// CHECK-NEXT: NestedNameSpecifier TypeSpecWithTemplate 'template U<int>':'U<int>'
// CHECK-NEXT: ImplicitCastExpr
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:3> 'U<int> *' lvalue ParmVar 0x{{[^ ]*}} 'r' 'U<int> *'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ int test() {
// CHECK-NEXT: | | `-ReturnStmt [[ADDR_22:0x[a-z0-9]*]] <line:10:3, col:10>
// CHECK-NEXT: | | `-IntegerLiteral [[ADDR_23:0x[a-z0-9]*]] <col:10> 'int' 0
// CHECK-NEXT: | `-FunctionDecl [[ADDR_24:0x[a-z0-9]*]] <line:9:1, line:11:1> line:9:5 used also_before_mismatch 'int ({{.*}})'
// CHECK-NEXT: | |-TemplateArgument integral 0
// CHECK-NEXT: | |-TemplateArgument integral '0'
// CHECK-NEXT: | `-CompoundStmt [[ADDR_25:0x[a-z0-9]*]] <col:32, line:11:1>
// CHECK-NEXT: | `-ReturnStmt [[ADDR_26:0x[a-z0-9]*]] <line:10:3, col:10>
// CHECK-NEXT: | `-IntegerLiteral [[ADDR_23]] <col:10> 'int' 0
Expand Down Expand Up @@ -179,7 +179,7 @@ int test() {
// CHECK-NEXT: | | `-OMPDeclareVariantAttr [[ADDR_101:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={extension(allow_templates)}
// CHECK-NEXT: | | `-DeclRefExpr [[ADDR_102:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' {{.*}}Function [[ADDR_103:0x[a-z0-9]*]] 'only_def[implementation={extension(allow_templates)}]' 'int ({{.*}})'
// CHECK-NEXT: | `-FunctionDecl [[ADDR_104:0x[a-z0-9]*]] <col:1, col:18> col:5 used only_def 'int ({{.*}})'
// CHECK-NEXT: | |-TemplateArgument integral 0
// CHECK-NEXT: | |-TemplateArgument integral '0'
// CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_105:0x[a-z0-9]*]] <<invalid sloc>> Implicit implementation={extension(allow_templates)}
// CHECK-NEXT: | `-DeclRefExpr [[ADDR_106:0x[a-z0-9]*]] <col:1> 'int ({{.*}})' {{.*}}Function [[ADDR_107:0x[a-z0-9]*]] 'only_def[implementation={extension(allow_templates)}]' 'int ({{.*}})'
// CHECK-NEXT: |-FunctionTemplateDecl [[ADDR_108:0x[a-z0-9]*]] <line:37:1, line:40:1> line:38:1 only_def[implementation={extension(allow_templates)}]
Expand All @@ -189,7 +189,7 @@ int test() {
// CHECK-NEXT: | | `-ReturnStmt [[ADDR_110:0x[a-z0-9]*]] <line:39:3, col:10>
// CHECK-NEXT: | | `-IntegerLiteral [[ADDR_111:0x[a-z0-9]*]] <col:10> 'int' 0
// CHECK-NEXT: | `-FunctionDecl [[ADDR_107]] <line:38:1, line:40:1> line:38:1 only_def[implementation={extension(allow_templates)}] 'int ({{.*}})'
// CHECK-NEXT: | |-TemplateArgument integral 0
// CHECK-NEXT: | |-TemplateArgument integral '0'
// CHECK-NEXT: | `-CompoundStmt [[ADDR_112:0x[a-z0-9]*]] <col:20, line:40:1>
// CHECK-NEXT: | `-ReturnStmt [[ADDR_113:0x[a-z0-9]*]] <line:39:3, col:10>
// CHECK-NEXT: | `-IntegerLiteral [[ADDR_111]] <col:10> 'int' 0
Expand Down
6 changes: 3 additions & 3 deletions clang/test/AST/ast-dump-template-decls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ template <class T> struct C {
using type2 = typename C<int>::type1<void>;
// CHECK: TypeAliasDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, col:42> col:7 type2 'typename C<int>::type1<void>':'void (int)'
// CHECK-NEXT: ElaboratedType 0x{{[^ ]*}} 'typename C<int>::type1<void>' sugar
// CHECK-NEXT: TemplateSpecializationType 0x{{[^ ]*}} 'type1<void>' sugar alias type1
// CHECK-NEXT: TemplateSpecializationType 0x{{[^ ]*}} 'type1<void>' sugar alias C<int>::type1
// CHECK-NEXT: TemplateArgument type 'void'
// CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'void'
// CHECK-NEXT: FunctionProtoType 0x{{[^ ]*}} 'void (int)' cdecl
Expand Down Expand Up @@ -149,7 +149,7 @@ template <typename... T> struct D {
template <typename... U> using B = int(int (*...p)(T, U));
};
using t2 = D<float, char>::B<int, short>;
// CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'B<int, short>' sugar alias B
// CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'B<int, short>' sugar alias D<float, char>::B{{$}}
// CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (int (*)(float, int), int (*)(char, short))' cdecl
// CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (float, int)' cdecl
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar typename depth 0 index 0 ... T pack_index 1
Expand All @@ -169,7 +169,7 @@ template<template<class C1, class C2 = A<C1>> class D1, class D2> using D = D1<D

template<class E1, class E2> class E {};
using test1 = D<E, int>;
// CHECK: TypeAliasDecl 0x{{[^ ]*}} <line:{{[1-9]+}}:1, col:23> col:7 test1 'D<subst_default_argument::E, int>':'subst_default_argument::E<int, subst_default_argument::A<int>>'
// CHECK: TypeAliasDecl 0x{{[^ ]*}} <line:{{[1-9]+}}:1, col:23> col:7 test1 'D<E, int>':'subst_default_argument::E<int, subst_default_argument::A<int>>'
// CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'A<int>' sugar A
// CHECK-NEXT: |-TemplateArgument type 'int'
// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 1 D2
Expand Down
54 changes: 54 additions & 0 deletions clang/test/AST/ast-dump-template-name.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// RUN: %clang_cc1 -std=c++26 -ast-dump -ast-dump-filter=Test %s | FileCheck %s

template <template <class> class TT> using N = TT<int>;

namespace qualified {
namespace foo {
template <class T> struct A;
} // namespace foo
using TestQualified = N<foo::A>;
} // namespace qualified

// CHECK: Dumping qualified::TestQualified:
// CHECK-NEXT: TypeAliasDecl
// CHECK-NEXT: `-ElaboratedType
// CHECK-NEXT: `-TemplateSpecializationType
// CHECK-NEXT: |-TemplateArgument template 'foo::A':'qualified::foo::A' qualified{{$}}
// CHECK-NEXT: | |-NestedNameSpecifier Namespace 0x{{.+}} 'foo'{{$}}
// CHECK-NEXT: | `-ClassTemplateDecl {{.+}} A{{$}}

namespace dependent {
template <class T> struct B {
using TestDependent = N<T::template X>;
};
} // namespace dependent

// CHECK: Dumping dependent::B::TestDependent:
// CHECK-NEXT: TypeAliasDecl
// CHECK-NEXT: `-ElaboratedType
// CHECK-NEXT: `-TemplateSpecializationType
// CHECK-NEXT: |-TemplateArgument template 'T::template X':'type-parameter-0-0::template X' dependent{{$}}
// CHECK-NEXT: | `-NestedNameSpecifier TypeSpec 'T'{{$}}

namespace subst {
template <class> struct A;

template <template <class> class TT> struct B {
template <template <class> class> struct C {};
using type = C<TT>;
};
using TestSubst = B<A>::type;
} // namespace subst

// CHECK: Dumping subst::TestSubst:
// CHECK-NEXT: TypeAliasDecl
// CHECK-NEXT: `-ElaboratedType
// CHECK-NEXT: `-TypedefType
// CHECK-NEXT: |-TypeAlias
// CHECK-NEXT: `-ElaboratedType
// CHECK-NEXT: `-TemplateSpecializationType
// CHECK-NEXT: |-TemplateArgument template 'subst::A' subst index 0
// CHECK-NEXT: | |-parameter: TemplateTemplateParmDecl {{.+}} depth 0 index 0 TT{{$}}
// CHECK-NEXT: | |-associated ClassTemplateSpecialization {{.+}} 'B'{{$}}
// CHECK-NEXT: | `-replacement:
// CHECK-NEXT: | `-ClassTemplateDecl {{.+}} A{{$}}
12 changes: 7 additions & 5 deletions clang/test/AST/ast-dump-using-template.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ using A = S<T>;
template <template <typename> class T> class X {};
using B = X<S>;
// CHECK: TypeAliasDecl
// CHECK-NEXT: `-ElaboratedType {{.*}} 'X<ns::S>' sugar
// CHECK-NEXT: `-TemplateSpecializationType {{.*}} 'X<ns::S>' sugar X
// CHECK-NEXT: |-TemplateArgument using template S
// CHECK-NEXT: `-RecordType {{.*}} 'X<ns::S>'
// CHECK-NEXT: `-ClassTemplateSpecialization {{.*}} 'X'
// CHECK-NEXT: `-ElaboratedType {{.*}} 'X<S>' sugar
// CHECK-NEXT: `-TemplateSpecializationType {{.*}} 'X<S>' sugar X
// CHECK-NEXT: |-TemplateArgument template 'S'
// CHECK-NEXT: | |-UsingShadowDecl {{.*}} implicit ClassTemplate {{.*}} 'S'
// CHECK-NEXT: | `-target: ClassTemplateDecl {{.*}} S
// CHECK-NEXT: `-RecordType {{.*}} 'X<ns::S>'
// CHECK-NEXT: `-ClassTemplateSpecialization {{.*}} 'X'

// TemplateName in DeducedTemplateSpecializationType.
S DeducedTemplateSpecializationT(123);
Expand Down
6 changes: 3 additions & 3 deletions clang/test/AST/constraints-explicit-instantiation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,17 @@ struct A {

// This checks that `canary1<1>` and `canaray2<2>` are instantiated, thus
// indirectly validating that the correct candidates of `A::f` were really
// instantiated each time.
// instantiated each time.
// The `static_assert`s validate we don't instantiate wrong candidates.

// CHECK:{{.*}}FunctionTemplateDecl {{.*}} canary1
// CHECK: {{.*}}TemplateArgument integral
// CHECK-SAME: {{1$}}
// CHECK-SAME: {{'1'$}}
template struct A<1>;

// CHECK: {{.*}}FunctionTemplateDecl {{.*}} canary2
// CHECK: {{.*}}TemplateArgument integral
// CHECK-SAME: {{2$}}
// CHECK-SAME: {{'2'$}}
template struct A<2>;

template struct A<3>;
Expand Down
20 changes: 20 additions & 0 deletions clang/test/Analysis/putenv-stack-array.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ int test_auto_var_subarray() {
return putenv(env + 100); // expected-warning{{The 'putenv' function should not be called with}}
}

int f_test_auto_var_call(char *env) {
return putenv(env); // expected-warning{{The 'putenv' function should not be called with}}
}

int test_auto_var_call() {
char env[1024];
return f_test_auto_var_call(env);
}

int test_constant() {
char *env = "TEST";
return putenv(env); // no-warning: data is not on the stack
Expand All @@ -68,3 +77,14 @@ void test_auto_var_reset() {
// become invalid.
putenv((char *)"NAME=anothervalue");
}

void f_main(char *env) {
putenv(env); // no warning: string allocated in stack of 'main'
}

int main(int argc, char **argv) {
char env[] = "NAME=value";
putenv(env); // no warning: string allocated in stack of 'main'
f_main(env);
return 0;
}
3 changes: 2 additions & 1 deletion clang/test/C/C99/block-scopes.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@

enum {a, b};
void different(void) {
if (sizeof(enum {b, a}) != sizeof(int))
if (sizeof(enum {b, a}) != sizeof(int)) {
_Static_assert(a == 1, "");
}
/* In C89, the 'b' found here would have been from the enum declaration in
* the controlling expression of the selection statement, not from the global
* declaration. In C99 and later, that enumeration is scoped to the 'if'
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CXX/drs/cwg1xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ namespace cwg136 { // cwg136: 3.4
void q() {
j(A(), A()); // ok, has default argument
}
extern "C" void k(int, int, int, int); // #cwg136-k
extern "C" void k(int, int, int, int); // #cwg136-k
namespace NSA {
struct A {
friend void cwg136::k(int, int, int, int = 0);
Expand Down Expand Up @@ -1048,7 +1048,7 @@ namespace cwg176 { // cwg176: 3.1
cwg176::X *p4; // #cwg176-p4
// cxx98-14-error@#cwg176-p4 {{use of class template 'cwg176::X' requires template arguments}}
// cxx98-14-note@#cwg176-X {{template is declared here}}
// since-cxx17-error@#cwg176-p4 {{use of class template 'X' requires template arguments; argument deduction not allowed in non-static class member}}
// since-cxx17-error@#cwg176-p4 {{use of class template 'cwg176::X' requires template arguments; argument deduction not allowed in non-static class member}}
// since-cxx17-note@#cwg176-X {{template is declared here}}
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ int a1 = 0 == A<1>(); // Should not find 2 as the requires clause does not match

namespace static_operators {
// Verify no crash.
struct X {
struct X {
bool operator ==(X const&); // expected-note {{ambiguity is between a regular call}}
// expected-note@-1 {{mark 'operator==' as const or add a matching 'operator!=' to resolve the ambiguity}}
static bool operator !=(X const&, X const&); // expected-error {{overloaded 'operator!=' cannot be a static member function}}
Expand Down Expand Up @@ -474,7 +474,7 @@ namespace ns {
template <class T> struct A {};
template <class T> struct B : A<T> {};

template <class T> bool operator==(B<T>, A<T>); // expected-note {{candidate template ignored: could not match 'B' against 'A'}}
template <class T> bool operator==(B<T>, A<T>); // expected-note {{candidate template ignored: could not match 'B' against 'ns::A'}}
template <class T> bool operator!=(B<T>, A<T>);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
template<typename ...Types> struct tuple;
template<unsigned> struct unsigned_c;

template<typename T, typename U>
template<typename T, typename U>
struct is_same {
static const bool value = false;
};
Expand Down Expand Up @@ -93,7 +93,7 @@ namespace DeduceNonTypeTemplateArgsInArray {
}

namespace DeduceWithDefaultArgs {
template<template<typename...> class Container> void f(Container<int>); // expected-note {{deduced type 'X<[...], (default) int>' of 1st parameter does not match adjusted type 'X<[...], double>' of argument [with Container = DeduceWithDefaultArgs::X]}}
template<template<typename...> class Container> void f(Container<int>); // expected-note {{deduced type 'X<[...], (default) int>' of 1st parameter does not match adjusted type 'X<[...], double>' of argument [with Container = X]}}
template<typename, typename = int> struct X {};
void g() {
// OK, use default argument for the second template parameter.
Expand Down
16 changes: 16 additions & 0 deletions clang/test/CodeCompletion/member-access.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -367,4 +367,20 @@ class A {
// CHECK-DEREF-THIS: [#void#]function()
}
};

template <typename Element>
struct RepeatedField {
void Add();
};

template <typename T>
RepeatedField<T>* MutableRepeatedField() {}

template <class T>
void Foo() {
auto& C = *MutableRepeatedField<T>();
C.
}
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:382:5 %s -o - | FileCheck -check-prefix=CHECK-DEREF-DEPENDENT %s
// CHECK-DEREF-DEPENDENT: [#void#]Add()
}
104 changes: 104 additions & 0 deletions clang/test/CodeGen/X86/x86-atomic-double.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
// RUN: %clang_cc1 -triple x86_64-linux-gnu -target-cpu core2 %s -emit-llvm -o - | FileCheck -check-prefixes=X64 %s
// RUN: %clang_cc1 -triple i686-linux-gnu -target-cpu core2 %s -emit-llvm -o - | FileCheck -check-prefixes=X86 %s


// X64-LABEL: define dso_local double @test_double_post_inc(
// X64-SAME: ) #[[ATTR0:[0-9]+]] {
// X64-NEXT: entry:
// X64-NEXT: [[RETVAL:%.*]] = alloca double, align 8
// X64-NEXT: [[TMP0:%.*]] = atomicrmw fadd ptr @test_double_post_inc.n, float 1.000000e+00 seq_cst, align 8
// X64-NEXT: store float [[TMP0]], ptr [[RETVAL]], align 8
// X64-NEXT: [[TMP1:%.*]] = load double, ptr [[RETVAL]], align 8
// X64-NEXT: ret double [[TMP1]]
//
// X86-LABEL: define dso_local double @test_double_post_inc(
// X86-SAME: ) #[[ATTR0:[0-9]+]] {
// X86-NEXT: entry:
// X86-NEXT: [[RETVAL:%.*]] = alloca double, align 4
// X86-NEXT: [[TMP0:%.*]] = atomicrmw fadd ptr @test_double_post_inc.n, float 1.000000e+00 seq_cst, align 8
// X86-NEXT: store float [[TMP0]], ptr [[RETVAL]], align 4
// X86-NEXT: [[TMP1:%.*]] = load double, ptr [[RETVAL]], align 4
// X86-NEXT: ret double [[TMP1]]
//
double test_double_post_inc()
{
static _Atomic double n;
return n++;
}

// X64-LABEL: define dso_local double @test_double_post_dc(
// X64-SAME: ) #[[ATTR0]] {
// X64-NEXT: entry:
// X64-NEXT: [[RETVAL:%.*]] = alloca double, align 8
// X64-NEXT: [[TMP0:%.*]] = atomicrmw fsub ptr @test_double_post_dc.n, float 1.000000e+00 seq_cst, align 8
// X64-NEXT: store float [[TMP0]], ptr [[RETVAL]], align 8
// X64-NEXT: [[TMP1:%.*]] = load double, ptr [[RETVAL]], align 8
// X64-NEXT: ret double [[TMP1]]
//
// X86-LABEL: define dso_local double @test_double_post_dc(
// X86-SAME: ) #[[ATTR0]] {
// X86-NEXT: entry:
// X86-NEXT: [[RETVAL:%.*]] = alloca double, align 4
// X86-NEXT: [[TMP0:%.*]] = atomicrmw fsub ptr @test_double_post_dc.n, float 1.000000e+00 seq_cst, align 8
// X86-NEXT: store float [[TMP0]], ptr [[RETVAL]], align 4
// X86-NEXT: [[TMP1:%.*]] = load double, ptr [[RETVAL]], align 4
// X86-NEXT: ret double [[TMP1]]
//
double test_double_post_dc()
{
static _Atomic double n;
return n--;
}

// X64-LABEL: define dso_local double @test_double_pre_dc(
// X64-SAME: ) #[[ATTR0]] {
// X64-NEXT: entry:
// X64-NEXT: [[RETVAL:%.*]] = alloca double, align 8
// X64-NEXT: [[TMP0:%.*]] = atomicrmw fsub ptr @test_double_pre_dc.n, float 1.000000e+00 seq_cst, align 8
// X64-NEXT: [[TMP1:%.*]] = fsub float [[TMP0]], 1.000000e+00
// X64-NEXT: store float [[TMP1]], ptr [[RETVAL]], align 8
// X64-NEXT: [[TMP2:%.*]] = load double, ptr [[RETVAL]], align 8
// X64-NEXT: ret double [[TMP2]]
//
// X86-LABEL: define dso_local double @test_double_pre_dc(
// X86-SAME: ) #[[ATTR0]] {
// X86-NEXT: entry:
// X86-NEXT: [[RETVAL:%.*]] = alloca double, align 4
// X86-NEXT: [[TMP0:%.*]] = atomicrmw fsub ptr @test_double_pre_dc.n, float 1.000000e+00 seq_cst, align 8
// X86-NEXT: [[TMP1:%.*]] = fsub float [[TMP0]], 1.000000e+00
// X86-NEXT: store float [[TMP1]], ptr [[RETVAL]], align 4
// X86-NEXT: [[TMP2:%.*]] = load double, ptr [[RETVAL]], align 4
// X86-NEXT: ret double [[TMP2]]
//
double test_double_pre_dc()
{
static _Atomic double n;
return --n;
}

// X64-LABEL: define dso_local double @test_double_pre_inc(
// X64-SAME: ) #[[ATTR0]] {
// X64-NEXT: entry:
// X64-NEXT: [[RETVAL:%.*]] = alloca double, align 8
// X64-NEXT: [[TMP0:%.*]] = atomicrmw fadd ptr @test_double_pre_inc.n, float 1.000000e+00 seq_cst, align 8
// X64-NEXT: [[TMP1:%.*]] = fadd float [[TMP0]], 1.000000e+00
// X64-NEXT: store float [[TMP1]], ptr [[RETVAL]], align 8
// X64-NEXT: [[TMP2:%.*]] = load double, ptr [[RETVAL]], align 8
// X64-NEXT: ret double [[TMP2]]
//
// X86-LABEL: define dso_local double @test_double_pre_inc(
// X86-SAME: ) #[[ATTR0]] {
// X86-NEXT: entry:
// X86-NEXT: [[RETVAL:%.*]] = alloca double, align 4
// X86-NEXT: [[TMP0:%.*]] = atomicrmw fadd ptr @test_double_pre_inc.n, float 1.000000e+00 seq_cst, align 8
// X86-NEXT: [[TMP1:%.*]] = fadd float [[TMP0]], 1.000000e+00
// X86-NEXT: store float [[TMP1]], ptr [[RETVAL]], align 4
// X86-NEXT: [[TMP2:%.*]] = load double, ptr [[RETVAL]], align 4
// X86-NEXT: ret double [[TMP2]]
//
double test_double_pre_inc()
{
static _Atomic double n;
return ++n;
}
19 changes: 8 additions & 11 deletions clang/test/CodeGen/X86/x86-atomic-float.c
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
// RUN: %clang_cc1 -triple x86_64-linux-gnu -target-cpu core2 %s -emit-llvm -o - | FileCheck -check-prefixes=CHECK,CHECK64 %s
// RUN: %clang_cc1 -triple i686-linux-gnu -target-cpu core2 %s -emit-llvm -o - | FileCheck -check-prefixes=CHECK,CHECK32 %s
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
// RUN: %clang_cc1 -triple x86_64-linux-gnu -target-cpu core2 %s -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -triple i686-linux-gnu -target-cpu core2 %s -emit-llvm -o - | FileCheck %s


// CHECK-LABEL: define dso_local i32 @test_int_inc(
// CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw add ptr @test_int_inc.n, i32 1 seq_cst, align 4
// CHECK-NEXT: ret i32 [[TMP0]]
//
Expand All @@ -17,7 +17,7 @@ int test_int_inc()

// CHECK-LABEL: define dso_local float @test_float_post_inc(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw fadd ptr @test_float_post_inc.n, float 1.000000e+00 seq_cst, align 4
// CHECK-NEXT: ret float [[TMP0]]
//
Expand All @@ -29,7 +29,7 @@ float test_float_post_inc()

// CHECK-LABEL: define dso_local float @test_float_post_dc(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw fsub ptr @test_float_post_dc.n, float 1.000000e+00 seq_cst, align 4
// CHECK-NEXT: ret float [[TMP0]]
//
Expand All @@ -41,7 +41,7 @@ float test_float_post_dc()

// CHECK-LABEL: define dso_local float @test_float_pre_dc(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw fsub ptr @test_float_pre_dc.n, float 1.000000e+00 seq_cst, align 4
// CHECK-NEXT: [[TMP1:%.*]] = fsub float [[TMP0]], 1.000000e+00
// CHECK-NEXT: ret float [[TMP1]]
Expand All @@ -54,7 +54,7 @@ float test_float_pre_dc()

// CHECK-LABEL: define dso_local float @test_float_pre_inc(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[TMP0:%.*]] = atomicrmw fadd ptr @test_float_pre_inc.n, float 1.000000e+00 seq_cst, align 4
// CHECK-NEXT: [[TMP1:%.*]] = fadd float [[TMP0]], 1.000000e+00
// CHECK-NEXT: ret float [[TMP1]]
Expand All @@ -64,6 +64,3 @@ float test_float_pre_inc()
static _Atomic float n;
return ++n;
}
//// NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
// CHECK32: {{.*}}
// CHECK64: {{.*}}
Loading