58 changes: 43 additions & 15 deletions clang/lib/Analysis/FlowSensitive/Transfer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,9 @@ namespace {

class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
public:
TransferVisitor(const StmtToEnvMap &StmtToEnv, Environment &Env)
: StmtToEnv(StmtToEnv), Env(Env) {}
TransferVisitor(const StmtToEnvMap &StmtToEnv, Environment &Env,
Environment::ValueModel &Model)
: StmtToEnv(StmtToEnv), Env(Env), Model(Model) {}

void VisitBinaryOperator(const BinaryOperator *S) {
const Expr *LHS = S->getLHS();
Expand Down Expand Up @@ -641,17 +642,42 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
}

void VisitConditionalOperator(const ConditionalOperator *S) {
// FIXME: Revisit this once flow conditions are added to the framework. For
// `a = b ? c : d` we can add `b => a == c && !b => a == d` to the flow
// condition.
// When we do this, we will need to retrieve the values of the operands from
// the environments for the basic blocks they are computed in, in a similar
// way to how this is done for short-circuited logical operators in
// `getLogicOperatorSubExprValue()`.
if (S->isGLValue())
Env.setStorageLocation(*S, Env.createObject(S->getType()));
else if (!S->getType()->isRecordType()) {
if (Value *Val = Env.createValue(S->getType()))
const Environment *TrueEnv = StmtToEnv.getEnvironment(*S->getTrueExpr());
const Environment *FalseEnv = StmtToEnv.getEnvironment(*S->getFalseExpr());

if (TrueEnv == nullptr || FalseEnv == nullptr) {
// If the true or false branch is dead, we may not have an environment for
// it. We could handle this specifically by forwarding the value or
// location of the live branch, but this case is rare enough that this
// probably isn't worth the additional complexity.
return;
}

if (S->isGLValue()) {
StorageLocation *TrueLoc = TrueEnv->getStorageLocation(*S->getTrueExpr());
StorageLocation *FalseLoc =
FalseEnv->getStorageLocation(*S->getFalseExpr());
if (TrueLoc == FalseLoc && TrueLoc != nullptr)
Env.setStorageLocation(*S, *TrueLoc);
} else if (!S->getType()->isRecordType()) {
// The conditional operator can evaluate to either of the values of the
// two branches. To model this, join these two values together to yield
// the result of the conditional operator.
// Note: Most joins happen in `computeBlockInputState()`, but this case is
// different:
// - `computeBlockInputState()` (which in turn calls `Environment::join()`
// joins values associated with the _same_ expression or storage
// location, then associates the joined value with that expression or
// storage location. This join has nothing to do with transfer --
// instead, it joins together the results of performing transfer on two
// different blocks.
// - Here, we join values associated with _different_ expressions (the
// true and false branch), then associate the joined value with a third
// expression (the conditional operator itself). This join is what it
// means to perform transfer on the conditional operator.
if (Value *Val = Environment::joinValues(
S->getType(), TrueEnv->getValue(*S->getTrueExpr()), *TrueEnv,
FalseEnv->getValue(*S->getFalseExpr()), *FalseEnv, Env, Model))
Env.setValue(*S, *Val);
}
}
Expand Down Expand Up @@ -810,12 +836,14 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {

const StmtToEnvMap &StmtToEnv;
Environment &Env;
Environment::ValueModel &Model;
};

} // namespace

void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env) {
TransferVisitor(StmtToEnv, Env).Visit(&S);
void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env,
Environment::ValueModel &Model) {
TransferVisitor(StmtToEnv, Env, Model).Visit(&S);
}

} // namespace dataflow
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ builtinTransferStatement(unsigned CurBlockID, const CFGStmt &Elt,
const Stmt *S = Elt.getStmt();
assert(S != nullptr);
transfer(StmtToEnvMap(AC.ACFG, AC.BlockStates, CurBlockID, InputState), *S,
InputState.Env);
InputState.Env, AC.Analysis);
}

/// Built-in transfer function for `CFGInitializer`.
Expand Down Expand Up @@ -452,7 +452,7 @@ transferCFGBlock(const CFGBlock &Block, AnalysisContext &AC,
// terminator condition, but not as a `CFGElement`. The condition of an if
// statement is one such example.
transfer(StmtToEnvMap(AC.ACFG, AC.BlockStates, Block.getBlockID(), State),
*TerminatorCond, State.Env);
*TerminatorCond, State.Env, AC.Analysis);

// If the transfer function didn't produce a value, create an atom so that
// we have *some* value for the condition expression. This ensures that
Expand Down
8 changes: 6 additions & 2 deletions clang/lib/Basic/Targets/PPC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
HasPrivileged = true;
} else if (Feature == "+aix-small-local-exec-tls") {
HasAIXSmallLocalExecTLS = true;
} else if (Feature == "+aix-small-local-dynamic-tls") {
HasAIXSmallLocalDynamicTLS = true;
} else if (Feature == "+isa-v206-instructions") {
IsISA2_06 = true;
} else if (Feature == "+isa-v207-instructions") {
Expand Down Expand Up @@ -573,9 +575,10 @@ bool PPCTargetInfo::initFeatureMap(
// Privileged instructions are off by default.
Features["privileged"] = false;

// The code generated by the -maix-small-local-exec-tls option is turned
// off by default.
// The code generated by the -maix-small-local-[exec|dynamic]-tls option is
// turned off by default.
Features["aix-small-local-exec-tls"] = false;
Features["aix-small-local-dynamic-tls"] = false;

Features["spe"] = llvm::StringSwitch<bool>(CPU)
.Case("8548", true)
Expand Down Expand Up @@ -713,6 +716,7 @@ bool PPCTargetInfo::hasFeature(StringRef Feature) const {
.Case("rop-protect", HasROPProtect)
.Case("privileged", HasPrivileged)
.Case("aix-small-local-exec-tls", HasAIXSmallLocalExecTLS)
.Case("aix-small-local-dynamic-tls", HasAIXSmallLocalDynamicTLS)
.Case("isa-v206-instructions", IsISA2_06)
.Case("isa-v207-instructions", IsISA2_07)
.Case("isa-v30-instructions", IsISA3_0)
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Basic/Targets/PPC.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo {
bool HasROPProtect = false;
bool HasPrivileged = false;
bool HasAIXSmallLocalExecTLS = false;
bool HasAIXSmallLocalDynamicTLS = false;
bool HasVSX = false;
bool UseCRBits = false;
bool HasP8Vector = false;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Basic/Targets/RISCV.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/RISCVISAInfo.h"
#include "llvm/TargetParser/RISCVISAInfo.h"
#include "llvm/TargetParser/Triple.h"
#include <optional>

Expand Down
30 changes: 19 additions & 11 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18267,8 +18267,8 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
if (!E->getArg(0)->getType()->hasFloatingRepresentation())
llvm_unreachable("lerp operand must have a float representation");
return Builder.CreateIntrinsic(
/*ReturnType=*/X->getType(), Intrinsic::dx_lerp,
ArrayRef<Value *>{X, Y, S}, nullptr, "dx.lerp");
/*ReturnType=*/X->getType(), CGM.getHLSLRuntime().getLerpIntrinsic(),
ArrayRef<Value *>{X, Y, S}, nullptr, "hlsl.lerp");
}
case Builtin::BI__builtin_hlsl_elementwise_frac: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
Expand Down Expand Up @@ -18296,20 +18296,28 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
Value *M = EmitScalarExpr(E->getArg(0));
Value *A = EmitScalarExpr(E->getArg(1));
Value *B = EmitScalarExpr(E->getArg(2));
if (E->getArg(0)->getType()->hasFloatingRepresentation()) {
if (E->getArg(0)->getType()->hasFloatingRepresentation())
return Builder.CreateIntrinsic(
/*ReturnType*/ M->getType(), Intrinsic::fmuladd,
ArrayRef<Value *>{M, A, B}, nullptr, "dx.fmad");
}
ArrayRef<Value *>{M, A, B}, nullptr, "hlsl.fmad");

if (E->getArg(0)->getType()->hasSignedIntegerRepresentation()) {
return Builder.CreateIntrinsic(
/*ReturnType*/ M->getType(), Intrinsic::dx_imad,
ArrayRef<Value *>{M, A, B}, nullptr, "dx.imad");
if (CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil)
return Builder.CreateIntrinsic(
/*ReturnType*/ M->getType(), Intrinsic::dx_imad,
ArrayRef<Value *>{M, A, B}, nullptr, "dx.imad");

Value *Mul = Builder.CreateNSWMul(M, A);
return Builder.CreateNSWAdd(Mul, B);
}
assert(E->getArg(0)->getType()->hasUnsignedIntegerRepresentation());
return Builder.CreateIntrinsic(
/*ReturnType=*/M->getType(), Intrinsic::dx_umad,
ArrayRef<Value *>{M, A, B}, nullptr, "dx.umad");
if (CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil)
return Builder.CreateIntrinsic(
/*ReturnType=*/M->getType(), Intrinsic::dx_umad,
ArrayRef<Value *>{M, A, B}, nullptr, "dx.umad");

Value *Mul = Builder.CreateNUWMul(M, A);
return Builder.CreateNUWAdd(Mul, B);
}
case Builtin::BI__builtin_hlsl_elementwise_rcp: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
Expand Down
6 changes: 2 additions & 4 deletions clang/lib/CodeGen/CGCoroutine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -413,10 +413,8 @@ llvm::Function *
CodeGenFunction::generateAwaitSuspendWrapper(Twine const &CoroName,
Twine const &SuspendPointName,
CoroutineSuspendExpr const &S) {
std::string FuncName = "__await_suspend_wrapper_";
FuncName += CoroName.str();
FuncName += '_';
FuncName += SuspendPointName.str();
std::string FuncName =
(CoroName + ".__await_suspend_wrapper__" + SuspendPointName).str();

ASTContext &C = getContext();

Expand Down
108 changes: 56 additions & 52 deletions clang/lib/CodeGen/CGExprConstant.cpp

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1540,7 +1540,7 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
if (auto DstPT = dyn_cast<llvm::PointerType>(DstTy)) {
// The source value may be an integer, or a pointer.
if (isa<llvm::PointerType>(SrcTy))
return Builder.CreateBitCast(Src, DstTy, "conv");
return Src;

assert(SrcType->isIntegerType() && "Not ptr->ptr or int->ptr conversion?");
// First, convert to the correct width so that we control the kind of
Expand Down
1 change: 1 addition & 0 deletions clang/lib/CodeGen/CGHLSLRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class CGHLSLRuntime {

GENERATE_HLSL_INTRINSIC_FUNCTION(All, all)
GENERATE_HLSL_INTRINSIC_FUNCTION(Any, any)
GENERATE_HLSL_INTRINSIC_FUNCTION(Lerp, lerp)
GENERATE_HLSL_INTRINSIC_FUNCTION(ThreadId, thread_id)

//===----------------------------------------------------------------------===//
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/RISCVISAInfo.h"
#include "llvm/Support/TimeProfiler.h"
#include "llvm/Support/xxhash.h"
#include "llvm/TargetParser/RISCVISAInfo.h"
#include "llvm/TargetParser/Triple.h"
#include "llvm/TargetParser/X86TargetParser.h"
#include <optional>
Expand Down
11 changes: 8 additions & 3 deletions clang/lib/CodeGen/CoverageMappingGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1208,6 +1208,12 @@ struct CounterCoverageMappingBuilder
/// Find a valid gap range between \p AfterLoc and \p BeforeLoc.
std::optional<SourceRange> findGapAreaBetween(SourceLocation AfterLoc,
SourceLocation BeforeLoc) {
// Some statements (like AttributedStmt and ImplicitValueInitExpr) don't
// have valid source locations. Do not emit a gap region if this is the case
// in either AfterLoc end or BeforeLoc end.
if (AfterLoc.isInvalid() || BeforeLoc.isInvalid())
return std::nullopt;

// If AfterLoc is in function-like macro, use the right parenthesis
// location.
if (AfterLoc.isMacroID()) {
Expand Down Expand Up @@ -1368,9 +1374,8 @@ struct CounterCoverageMappingBuilder
for (const Stmt *Child : S->children())
if (Child) {
// If last statement contains terminate statements, add a gap area
// between the two statements. Skipping attributed statements, because
// they don't have valid start location.
if (LastStmt && HasTerminateStmt && !isa<AttributedStmt>(Child)) {
// between the two statements.
if (LastStmt && HasTerminateStmt) {
auto Gap = findGapAreaBetween(getEnd(LastStmt), getStart(Child));
if (Gap)
fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(),
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,12 @@
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/RISCVISAInfo.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/StringSaver.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Host.h"
#include "llvm/TargetParser/RISCVISAInfo.h"
#include <cstdlib> // ::getenv
#include <map>
#include <memory>
Expand Down
8 changes: 6 additions & 2 deletions clang/lib/Driver/SanitizerArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1192,7 +1192,9 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
BinaryMetadataIgnorelistFiles);
}

if (TC.getTriple().isOSWindows() && needsUbsanRt()) {
if (TC.getTriple().isOSWindows() && needsUbsanRt() &&
Args.hasFlag(options::OPT_frtlib_defaultlib,
options::OPT_fno_rtlib_defaultlib, true)) {
// Instruct the code generator to embed linker directives in the object file
// that cause the required runtime libraries to be linked.
CmdArgs.push_back(
Expand All @@ -1203,7 +1205,9 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
"--dependent-lib=" +
TC.getCompilerRTBasename(Args, "ubsan_standalone_cxx")));
}
if (TC.getTriple().isOSWindows() && needsStatsRt()) {
if (TC.getTriple().isOSWindows() && needsStatsRt() &&
Args.hasFlag(options::OPT_frtlib_defaultlib,
options::OPT_fno_rtlib_defaultlib, true)) {
CmdArgs.push_back(Args.MakeArgString(
"--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats_client")));

Expand Down
17 changes: 9 additions & 8 deletions clang/lib/Driver/ToolChains/Arch/PPC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,21 +125,22 @@ void ppc::getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple,

bool UseSeparateSections = isUseSeparateSections(Triple);
bool HasDefaultDataSections = Triple.isOSBinFormatXCOFF();
if (Args.hasArg(options::OPT_maix_small_local_exec_tls)) {
if (Args.hasArg(options::OPT_maix_small_local_exec_tls) ||
Args.hasArg(options::OPT_maix_small_local_dynamic_tls)) {
if (!Triple.isOSAIX() || !Triple.isArch64Bit())
D.Diag(diag::err_opt_not_valid_on_target) << "-maix-small-local-exec-tls";
D.Diag(diag::err_opt_not_valid_on_target)
<< "-maix-small-local-[exec|dynamic]-tls";

// The -maix-small-local-exec-tls option should only be used with
// The -maix-small-local-[exec|dynamic]-tls option should only be used with
// -fdata-sections, as having data sections turned off with this option
// is not ideal for performance. Moreover, the small-local-exec-tls region
// is a limited resource, and should not be used for variables that may
// be replaced.
// is not ideal for performance. Moreover, the
// small-local-[exec|dynamic]-tls region is a limited resource, and should
// not be used for variables that may be replaced.
if (!Args.hasFlag(options::OPT_fdata_sections,
options::OPT_fno_data_sections,
UseSeparateSections || HasDefaultDataSections))
D.Diag(diag::err_drv_argument_only_allowed_with)
<< "-maix-small-local-exec-tls"
<< "-fdata-sections";
<< "-maix-small-local-[exec|dynamic]-tls" << "-fdata-sections";
}
}

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/Arch/RISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
#include "clang/Driver/Options.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/RISCVISAInfo.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Host.h"
#include "llvm/TargetParser/RISCVISAInfo.h"
#include "llvm/TargetParser/RISCVTargetParser.h"

using namespace clang::driver;
Expand Down
22 changes: 18 additions & 4 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/RISCVISAInfo.h"
#include "llvm/Support/YAMLParser.h"
#include "llvm/TargetParser/ARMTargetParserCommon.h"
#include "llvm/TargetParser/Host.h"
#include "llvm/TargetParser/LoongArchTargetParser.h"
#include "llvm/TargetParser/RISCVISAInfo.h"
#include "llvm/TargetParser/RISCVTargetParser.h"
#include <cctype>

Expand Down Expand Up @@ -637,7 +637,9 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C,
ProfileGenerateArg->getValue()));
// The default is to use Clang Instrumentation.
CmdArgs.push_back("-fprofile-instrument=clang");
if (TC.getTriple().isWindowsMSVCEnvironment()) {
if (TC.getTriple().isWindowsMSVCEnvironment() &&
Args.hasFlag(options::OPT_frtlib_defaultlib,
options::OPT_fno_rtlib_defaultlib, true)) {
// Add dependent lib for clang_rt.profile
CmdArgs.push_back(Args.MakeArgString(
"--dependent-lib=" + TC.getCompilerRTBasename(Args, "profile")));
Expand All @@ -656,7 +658,9 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C,
CmdArgs.push_back("-fprofile-instrument=csllvm");
}
if (PGOGenArg) {
if (TC.getTriple().isWindowsMSVCEnvironment()) {
if (TC.getTriple().isWindowsMSVCEnvironment() &&
Args.hasFlag(options::OPT_frtlib_defaultlib,
options::OPT_fno_rtlib_defaultlib, true)) {
// Add dependent lib for clang_rt.profile
CmdArgs.push_back(Args.MakeArgString(
"--dependent-lib=" + TC.getCompilerRTBasename(Args, "profile")));
Expand Down Expand Up @@ -847,6 +851,16 @@ static bool UseRelaxAll(Compilation &C, const ArgList &Args) {
if (Arg *A = Args.getLastArg(options::OPT_O_Group))
RelaxDefault = A->getOption().matches(options::OPT_O0);

// RISC-V requires an indirect jump for offsets larger than 1MiB. This cannot
// be done by assembler branch relaxation as it needs a free temporary
// register. Because of this, branch relaxation is handled by a MachineIR
// pass before the assembler. Forcing assembler branch relaxation for -O0
// makes the MachineIR branch relaxation inaccurate and it will miss cases
// where an indirect branch is necessary. To avoid this issue we are
// sacrificing the compile time improvement of using -mrelax-all for -O0.
if (C.getDefaultToolChain().getTriple().isRISCV())
RelaxDefault = false;

if (RelaxDefault) {
RelaxDefault = false;
for (const auto &Act : C.getActions()) {
Expand Down Expand Up @@ -4634,7 +4648,7 @@ renderDebugOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T,

// Emit DW_TAG_template_alias for template aliases? True by default for SCE.
bool UseDebugTemplateAlias =
DebuggerTuning == llvm::DebuggerKind::SCE && RequestedDWARFVersion >= 5;
DebuggerTuning == llvm::DebuggerKind::SCE && RequestedDWARFVersion >= 4;
if (const auto *DebugTemplateAlias = Args.getLastArg(
options::OPT_gtemplate_alias, options::OPT_gno_template_alias)) {
// DW_TAG_template_alias is only supported from DWARFv5 but if a user
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Driver/ToolChains/Flang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#include "llvm/Frontend/Debug/Options.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/RISCVISAInfo.h"
#include "llvm/TargetParser/RISCVISAInfo.h"
#include "llvm/TargetParser/RISCVTargetParser.h"

#include <cassert>
Expand Down Expand Up @@ -118,7 +118,7 @@ void Flang::addOtherOptions(const ArgList &Args, ArgStringList &CmdArgs) const {
Arg *gNArg = Args.getLastArg(options::OPT_gN_Group);
DebugInfoKind = debugLevelToInfoKind(*gNArg);
} else if (Args.hasArg(options::OPT_g_Flag)) {
DebugInfoKind = llvm::codegenoptions::DebugLineTablesOnly;
DebugInfoKind = llvm::codegenoptions::FullDebugInfo;
} else {
DebugInfoKind = llvm::codegenoptions::NoDebugInfo;
}
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/Gnu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@
#include "llvm/Option/ArgList.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/RISCVISAInfo.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/TargetParser/RISCVISAInfo.h"
#include "llvm/TargetParser/TargetParser.h"
#include <system_error>

Expand Down
28 changes: 15 additions & 13 deletions clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,27 +164,29 @@ std::optional<Array> serializeAvailability(const AvailabilityInfo &Avail) {
if (Avail.isDefault())
return std::nullopt;

Object Availability;
Array AvailabilityArray;
Availability["domain"] = Avail.Domain;
serializeObject(Availability, "introduced",
serializeSemanticVersion(Avail.Introduced));
serializeObject(Availability, "deprecated",
serializeSemanticVersion(Avail.Deprecated));
serializeObject(Availability, "obsoleted",
serializeSemanticVersion(Avail.Obsoleted));

if (Avail.isUnconditionallyDeprecated()) {
Object UnconditionallyDeprecated;
UnconditionallyDeprecated["domain"] = "*";
UnconditionallyDeprecated["isUnconditionallyDeprecated"] = true;
AvailabilityArray.emplace_back(std::move(UnconditionallyDeprecated));
}
if (Avail.isUnconditionallyUnavailable()) {
Object UnconditionallyUnavailable;
UnconditionallyUnavailable["domain"] = "*";
UnconditionallyUnavailable["isUnconditionallyUnavailable"] = true;
AvailabilityArray.emplace_back(std::move(UnconditionallyUnavailable));
Object Availability;

Availability["domain"] = Avail.Domain;

if (Avail.isUnavailable()) {
Availability["isUnconditionallyUnavailable"] = true;
} else {
serializeObject(Availability, "introduced",
serializeSemanticVersion(Avail.Introduced));
serializeObject(Availability, "deprecated",
serializeSemanticVersion(Avail.Deprecated));
serializeObject(Availability, "obsoleted",
serializeSemanticVersion(Avail.Obsoleted));
}

AvailabilityArray.emplace_back(std::move(Availability));
return AvailabilityArray;
}
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1543,6 +1543,7 @@ class AnnotatingParser {
return false;
if (Line.MustBeDeclaration && Contexts.size() == 1 &&
!Contexts.back().IsExpression && !Line.startsWith(TT_ObjCProperty) &&
!Line.startsWith(tok::l_paren) &&
!Tok->isOneOf(TT_TypeDeclarationParen, TT_RequiresExpressionLParen)) {
if (const auto *Previous = Tok->Previous;
!Previous ||
Expand Down Expand Up @@ -2726,8 +2727,10 @@ class AnnotatingParser {
}
}

if (Tok.Next->isOneOf(tok::question, tok::ampamp))
if (Tok.Next->is(tok::question) ||
(Tok.Next->is(tok::ampamp) && !Tok.Previous->isTypeName(IsCpp))) {
return false;
}

// `foreach((A a, B b) in someList)` should not be seen as a cast.
if (Tok.Next->is(Keywords.kw_in) && Style.isCSharp())
Expand Down
24 changes: 19 additions & 5 deletions clang/lib/Interpreter/IncrementalParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,10 @@ IncrementalParser::IncrementalParser(Interpreter &Interp,
if (Err)
return;
CI->ExecuteAction(*Act);

if (getCodeGen())
CachedInCodeGenModule = GenModule();

std::unique_ptr<ASTConsumer> IncrConsumer =
std::make_unique<IncrementalASTConsumer>(Interp, CI->takeASTConsumer());
CI->setASTConsumer(std::move(IncrConsumer));
Expand All @@ -224,11 +228,8 @@ IncrementalParser::IncrementalParser(Interpreter &Interp,
return; // PTU.takeError();
}

if (CodeGenerator *CG = getCodeGen()) {
std::unique_ptr<llvm::Module> M(CG->ReleaseModule());
CG->StartModule("incr_module_" + std::to_string(PTUs.size()),
M->getContext());
PTU->TheModule = std::move(M);
if (getCodeGen()) {
PTU->TheModule = GenModule();
assert(PTU->TheModule && "Failed to create initial PTU");
}
}
Expand Down Expand Up @@ -364,6 +365,19 @@ IncrementalParser::Parse(llvm::StringRef input) {
std::unique_ptr<llvm::Module> IncrementalParser::GenModule() {
static unsigned ID = 0;
if (CodeGenerator *CG = getCodeGen()) {
// Clang's CodeGen is designed to work with a single llvm::Module. In many
// cases for convenience various CodeGen parts have a reference to the
// llvm::Module (TheModule or Module) which does not change when a new
// module is pushed. However, the execution engine wants to take ownership
// of the module which does not map well to CodeGen's design. To work this
// around we created an empty module to make CodeGen happy. We should make
// sure it always stays empty.
assert((!CachedInCodeGenModule ||
(CachedInCodeGenModule->empty() &&
CachedInCodeGenModule->global_empty() &&
CachedInCodeGenModule->alias_empty() &&
CachedInCodeGenModule->ifunc_empty())) &&
"CodeGen wrote to a readonly module");
std::unique_ptr<llvm::Module> M(CG->ReleaseModule());
CG->StartModule("incr_module_" + std::to_string(ID++), M->getContext());
return M;
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Interpreter/IncrementalParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <memory>
namespace llvm {
class LLVMContext;
class Module;
} // namespace llvm

namespace clang {
Expand Down Expand Up @@ -57,6 +58,10 @@ class IncrementalParser {
/// of code.
std::list<PartialTranslationUnit> PTUs;

/// When CodeGen is created the first llvm::Module gets cached in many places
/// and we must keep it alive.
std::unique_ptr<llvm::Module> CachedInCodeGenModule;

IncrementalParser();

public:
Expand Down
36 changes: 32 additions & 4 deletions clang/lib/Lex/LiteralSupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -974,6 +974,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
bool isFixedPointConstant = isFixedPointLiteral();
bool isFPConstant = isFloatingLiteral();
bool HasSize = false;
bool DoubleUnderscore = false;

// Loop over all of the characters of the suffix. If we see something bad,
// we break out of the loop.
Expand Down Expand Up @@ -1117,6 +1118,31 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
if (isImaginary) break; // Cannot be repeated.
isImaginary = true;
continue; // Success.
case '_':
if (isFPConstant)
break; // Invalid for floats
if (HasSize)
break;
if (DoubleUnderscore)
break; // Cannot be repeated.
if (LangOpts.CPlusPlus && s + 2 < ThisTokEnd &&
s[1] == '_') { // s + 2 < ThisTokEnd to ensure some character exists
// after __
DoubleUnderscore = true;
s += 2; // Skip both '_'
if (s + 1 < ThisTokEnd &&
(*s == 'u' || *s == 'U')) { // Ensure some character after 'u'/'U'
isUnsigned = true;
++s;
}
if (s + 1 < ThisTokEnd &&
((*s == 'w' && *(++s) == 'b') || (*s == 'W' && *(++s) == 'B'))) {
isBitInt = true;
HasSize = true;
continue;
}
}
break;
case 'w':
case 'W':
if (isFPConstant)
Expand All @@ -1127,9 +1153,9 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
// wb and WB are allowed, but a mixture of cases like Wb or wB is not. We
// explicitly do not support the suffix in C++ as an extension because a
// library-based UDL that resolves to a library type may be more
// appropriate there.
if (!LangOpts.CPlusPlus && ((s[0] == 'w' && s[1] == 'b') ||
(s[0] == 'W' && s[1] == 'B'))) {
// appropriate there. The same rules apply for __wb/__WB.
if ((!LangOpts.CPlusPlus || DoubleUnderscore) && s + 1 < ThisTokEnd &&
((s[0] == 'w' && s[1] == 'b') || (s[0] == 'W' && s[1] == 'B'))) {
isBitInt = true;
HasSize = true;
++s; // Skip both characters (2nd char skipped on continue).
Expand Down Expand Up @@ -1241,7 +1267,9 @@ bool NumericLiteralParser::isValidUDSuffix(const LangOptions &LangOpts,
return false;

// By C++11 [lex.ext]p10, ud-suffixes starting with an '_' are always valid.
if (Suffix[0] == '_')
// Suffixes starting with '__' (double underscore) are for use by
// the implementation.
if (Suffix.starts_with("_") && !Suffix.starts_with("__"))
return true;

// In C++11, there are no library suffixes.
Expand Down
8 changes: 4 additions & 4 deletions clang/lib/Lex/PPExpressions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,11 +333,11 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
: diag::ext_cxx23_size_t_suffix
: diag::err_cxx23_size_t_suffix);

// 'wb/uwb' literals are a C23 feature. We explicitly do not support the
// suffix in C++ as an extension because a library-based UDL that resolves
// to a library type may be more appropriate there.
// 'wb/uwb' literals are a C23 feature.
// '__wb/__uwb' are a C++ extension.
if (Literal.isBitInt)
PP.Diag(PeekTok, PP.getLangOpts().C23
PP.Diag(PeekTok, PP.getLangOpts().CPlusPlus ? diag::ext_cxx_bitint_suffix
: PP.getLangOpts().C23
? diag::warn_c23_compat_bitint_suffix
: diag::ext_c23_bitint_suffix);

Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Parse/ParseCXXInlineMethods.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,8 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) {
// to be re-used for method bodies as well.
ParseScope FnScope(this, Scope::FnScope | Scope::DeclScope |
Scope::CompoundStmtScope);
Sema::FPFeaturesStateRAII SaveFPFeatures(Actions);

Actions.ActOnStartOfFunctionDef(getCurScope(), LM.D);

if (Tok.is(tok::kw_try)) {
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2222,7 +2222,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
}

if (getLangOpts().HLSL)
MaybeParseHLSLSemantics(D);
MaybeParseHLSLAnnotations(D);

if (Tok.is(tok::kw_requires))
ParseTrailingRequiresClause(D);
Expand Down Expand Up @@ -2469,7 +2469,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
ParseDeclarator(D);

if (getLangOpts().HLSL)
MaybeParseHLSLSemantics(D);
MaybeParseHLSLAnnotations(D);

if (!D.isInvalidType()) {
// C++2a [dcl.decl]p1
Expand Down Expand Up @@ -7699,7 +7699,7 @@ void Parser::ParseParameterDeclarationClause(
// Parse GNU attributes, if present.
MaybeParseGNUAttributes(ParmDeclarator);
if (getLangOpts().HLSL)
MaybeParseHLSLSemantics(DS.getAttributes());
MaybeParseHLSLAnnotations(DS.getAttributes());

if (Tok.is(tok::kw_requires)) {
// User tried to define a requires clause in a parameter declaration,
Expand Down
18 changes: 8 additions & 10 deletions clang/lib/Parse/ParseHLSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Decl *Parser::ParseHLSLBuffer(SourceLocation &DeclEnd) {
SourceLocation IdentifierLoc = ConsumeToken();

ParsedAttributes Attrs(AttrFactory);
MaybeParseHLSLSemantics(Attrs, nullptr);
MaybeParseHLSLAnnotations(Attrs, nullptr);

ParseScope BufferScope(this, Scope::DeclScope);
BalancedDelimiterTracker T(*this, tok::l_brace);
Expand Down Expand Up @@ -118,12 +118,10 @@ static void fixSeparateAttrArgAndNumber(StringRef ArgStr, SourceLocation ArgLoc,
Slot = IdentifierLoc::create(Ctx, ArgLoc, PP.getIdentifierInfo(FixedArg));
}

void Parser::ParseHLSLSemantics(ParsedAttributes &Attrs,
SourceLocation *EndLoc) {
// FIXME: HLSLSemantic is shared for Semantic and resource binding which is
// confusing. Need a better name to avoid misunderstanding. Issue
// https://github.com/llvm/llvm-project/issues/57882
assert(Tok.is(tok::colon) && "Not a HLSL Semantic");
void Parser::ParseHLSLAnnotations(ParsedAttributes &Attrs,
SourceLocation *EndLoc) {

assert(Tok.is(tok::colon) && "Not a HLSL Annotation");
ConsumeToken();

IdentifierInfo *II = nullptr;
Expand All @@ -141,7 +139,7 @@ void Parser::ParseHLSLSemantics(ParsedAttributes &Attrs,
if (EndLoc)
*EndLoc = Tok.getLocation();
ParsedAttr::Kind AttrKind =
ParsedAttr::getParsedKind(II, nullptr, ParsedAttr::AS_HLSLSemantic);
ParsedAttr::getParsedKind(II, nullptr, ParsedAttr::AS_HLSLAnnotation);

ArgsVector ArgExprs;
switch (AttrKind) {
Expand Down Expand Up @@ -192,10 +190,10 @@ void Parser::ParseHLSLSemantics(ParsedAttributes &Attrs,
case ParsedAttr::AT_HLSLSV_DispatchThreadID:
break;
default:
llvm_unreachable("invalid HLSL Semantic");
llvm_unreachable("invalid HLSL Annotation");
break;
}

Attrs.addNew(II, Loc, nullptr, SourceLocation(), ArgExprs.data(),
ArgExprs.size(), ParsedAttr::Form::HLSLSemantic());
ArgExprs.size(), ParsedAttr::Form::HLSLAnnotation());
}
1 change: 1 addition & 0 deletions clang/lib/Parse/ParseObjc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3736,6 +3736,7 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {
ParseScope BodyScope(this, (parseMethod ? Scope::ObjCMethodScope : 0) |
Scope::FnScope | Scope::DeclScope |
Scope::CompoundStmtScope);
Sema::FPFeaturesStateRAII SaveFPFeatures(Actions);

// Tell the actions module that we have entered a method or c-function definition
// with the specified Declarator for the method/function.
Expand Down
87 changes: 70 additions & 17 deletions clang/lib/Parse/ParseOpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -632,16 +632,54 @@ Parser::ParseOpenACCClauseList(OpenACCDirectiveKind DirKind) {
return Clauses;
}

ExprResult Parser::ParseOpenACCIntExpr(OpenACCDirectiveKind DK,
OpenACCClauseKind CK,
SourceLocation Loc) {
ExprResult ER =
getActions().CorrectDelayedTyposInExpr(ParseAssignmentExpression());
Parser::OpenACCIntExprParseResult
Parser::ParseOpenACCIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
SourceLocation Loc) {
ExprResult ER = ParseAssignmentExpression();

// If the actual parsing failed, we don't know the state of the parse, so
// don't try to continue.
if (!ER.isUsable())
return ER;
return {ER, OpenACCParseCanContinue::Cannot};

// Parsing can continue after the initial assignment expression parsing, so
// even if there was a typo, we can continue.
ER = getActions().CorrectDelayedTyposInExpr(ER);
if (!ER.isUsable())
return {ER, OpenACCParseCanContinue::Can};

return {getActions().OpenACC().ActOnIntExpr(DK, CK, Loc, ER.get()),
OpenACCParseCanContinue::Can};
}

bool Parser::ParseOpenACCIntExprList(OpenACCDirectiveKind DK,
OpenACCClauseKind CK, SourceLocation Loc,
llvm::SmallVectorImpl<Expr *> &IntExprs) {
OpenACCIntExprParseResult CurResult = ParseOpenACCIntExpr(DK, CK, Loc);

if (!CurResult.first.isUsable() &&
CurResult.second == OpenACCParseCanContinue::Cannot) {
SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
Parser::StopBeforeMatch);
return true;
}

IntExprs.push_back(CurResult.first.get());

while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
ExpectAndConsume(tok::comma);

CurResult = ParseOpenACCIntExpr(DK, CK, Loc);

return getActions().OpenACC().ActOnIntExpr(DK, CK, Loc, ER.get());
if (!CurResult.first.isUsable() &&
CurResult.second == OpenACCParseCanContinue::Cannot) {
SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
Parser::StopBeforeMatch);
return true;
}
IntExprs.push_back(CurResult.first.get());
}
return false;
}

bool Parser::ParseOpenACCClauseVarList(OpenACCClauseKind Kind) {
Expand Down Expand Up @@ -761,7 +799,7 @@ bool Parser::ParseOpenACCGangArg(SourceLocation GangLoc) {
ConsumeToken();
return ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid,
OpenACCClauseKind::Gang, GangLoc)
.isInvalid();
.first.isInvalid();
}

if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Num, getCurToken()) &&
Expand All @@ -773,7 +811,7 @@ bool Parser::ParseOpenACCGangArg(SourceLocation GangLoc) {
// This is just the 'num' case where 'num' is optional.
return ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid,
OpenACCClauseKind::Gang, GangLoc)
.isInvalid();
.first.isInvalid();
}

bool Parser::ParseOpenACCGangArgList(SourceLocation GangLoc) {
Expand Down Expand Up @@ -946,13 +984,25 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams(
}
break;
}
case OpenACCClauseKind::NumGangs:
case OpenACCClauseKind::NumGangs: {
llvm::SmallVector<Expr *> IntExprs;

if (ParseOpenACCIntExprList(OpenACCDirectiveKind::Invalid,
OpenACCClauseKind::NumGangs, ClauseLoc,
IntExprs)) {
Parens.skipToEnd();
return OpenACCCanContinue();
}
ParsedClause.setIntExprDetails(std::move(IntExprs));
break;
}
case OpenACCClauseKind::NumWorkers:
case OpenACCClauseKind::DeviceNum:
case OpenACCClauseKind::DefaultAsync:
case OpenACCClauseKind::VectorLength: {
ExprResult IntExpr = ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid,
ClauseKind, ClauseLoc);
ClauseKind, ClauseLoc)
.first;
if (IntExpr.isInvalid()) {
Parens.skipToEnd();
return OpenACCCanContinue();
Expand Down Expand Up @@ -1017,7 +1067,8 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams(
: OpenACCSpecialTokenKind::Num,
ClauseKind);
ExprResult IntExpr = ParseOpenACCIntExpr(OpenACCDirectiveKind::Invalid,
ClauseKind, ClauseLoc);
ClauseKind, ClauseLoc)
.first;
if (IntExpr.isInvalid()) {
Parens.skipToEnd();
return OpenACCCanContinue();
Expand Down Expand Up @@ -1081,11 +1132,13 @@ bool Parser::ParseOpenACCWaitArgument(SourceLocation Loc, bool IsDirective) {
// Consume colon.
ConsumeToken();

ExprResult IntExpr = ParseOpenACCIntExpr(
IsDirective ? OpenACCDirectiveKind::Wait
: OpenACCDirectiveKind::Invalid,
IsDirective ? OpenACCClauseKind::Invalid : OpenACCClauseKind::Wait,
Loc);
ExprResult IntExpr =
ParseOpenACCIntExpr(IsDirective ? OpenACCDirectiveKind::Wait
: OpenACCDirectiveKind::Invalid,
IsDirective ? OpenACCClauseKind::Invalid
: OpenACCClauseKind::Wait,
Loc)
.first;
if (IntExpr.isInvalid())
return true;

Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Parse/ParseTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -733,7 +733,12 @@ NamedDecl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
// we introduce the type parameter into the local scope.
SourceLocation EqualLoc;
ParsedType DefaultArg;
std::optional<DelayTemplateIdDestructionRAII> DontDestructTemplateIds;
if (TryConsumeToken(tok::equal, EqualLoc)) {
// The default argument might contain a lambda declaration; avoid destroying
// parsed template ids at the end of that declaration because they can be
// used in a type constraint later.
DontDestructTemplateIds.emplace(*this, /*DelayTemplateIdDestruction=*/true);
// The default argument may declare template parameters, notably
// if it contains a generic lambda, so we need to increase
// the template depth as these parameters would not be instantiated
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Parse/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1497,6 +1497,8 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
return Actions.ActOnFinishFunctionBody(Res, nullptr, false);
}

Sema::FPFeaturesStateRAII SaveFPFeatures(Actions);

if (Tok.is(tok::kw_try))
return ParseFunctionTryBlock(Res, BodyScope);

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/MultiplexExternalSemaSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ void MultiplexExternalSemaSource::AddSource(ExternalSemaSource *Source) {
// ExternalASTSource.
//===----------------------------------------------------------------------===//

Decl *MultiplexExternalSemaSource::GetExternalDecl(uint32_t ID) {
Decl *MultiplexExternalSemaSource::GetExternalDecl(Decl::DeclID ID) {
for(size_t i = 0; i < Sources.size(); ++i)
if (Decl *Result = Sources[i]->GetExternalDecl(ID))
return Result;
Expand Down
11 changes: 8 additions & 3 deletions clang/lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12779,10 +12779,15 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
// In this case, the expression could be printed using a different
// specifier, but we've decided that the specifier is probably correct
// and we should cast instead. Just use the normal warning message.

unsigned Diag =
IsScopedEnum
? diag::warn_format_conversion_argument_type_mismatch_pedantic
: diag::warn_format_conversion_argument_type_mismatch;

EmitFormatDiagnostic(
S.PDiag(diag::warn_format_conversion_argument_type_mismatch)
<< AT.getRepresentativeTypeName(S.Context) << ExprTy << IsEnum
<< E->getSourceRange(),
S.PDiag(Diag) << AT.getRepresentativeTypeName(S.Context) << ExprTy
<< IsEnum << E->getSourceRange(),
E->getBeginLoc(), /*IsStringLocation*/ false, SpecRange, Hints);
}
}
Expand Down
7 changes: 2 additions & 5 deletions clang/lib/Sema/SemaCoroutine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -817,13 +817,10 @@ ExprResult Sema::BuildOperatorCoawaitLookupExpr(Scope *S, SourceLocation Loc) {

assert(!Operators.isAmbiguous() && "Operator lookup cannot be ambiguous");
const auto &Functions = Operators.asUnresolvedSet();
bool IsOverloaded =
Functions.size() > 1 ||
(Functions.size() == 1 && isa<FunctionTemplateDecl>(*Functions.begin()));
Expr *CoawaitOp = UnresolvedLookupExpr::Create(
Context, /*NamingClass*/ nullptr, NestedNameSpecifierLoc(),
DeclarationNameInfo(OpName, Loc), /*RequiresADL*/ true, IsOverloaded,
Functions.begin(), Functions.end());
DeclarationNameInfo(OpName, Loc), /*RequiresADL*/ true, Functions.begin(),
Functions.end(), /*KnownDependent=*/false);
assert(CoawaitOp);
return CoawaitOp;
}
Expand Down
23 changes: 21 additions & 2 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1240,8 +1240,8 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS,
Result.suppressDiagnostics();
return NameClassification::OverloadSet(UnresolvedLookupExpr::Create(
Context, Result.getNamingClass(), SS.getWithLocInContext(Context),
Result.getLookupNameInfo(), ADL, Result.isOverloadedResult(),
Result.begin(), Result.end()));
Result.getLookupNameInfo(), ADL, Result.begin(), Result.end(),
/*KnownDependent=*/false));
}

ExprResult
Expand Down Expand Up @@ -15899,6 +15899,11 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
FD->setInvalidDecl();
return D;
}

// Some function attributes (like OptimizeNoneAttr) need actions before
// parsing body started.
applyFunctionAttributesBeforeParsingBody(D);

// We want to attach documentation to original Decl (which might be
// a function template).
ActOnDocumentableDecl(D);
Expand All @@ -15910,6 +15915,20 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
return D;
}

void Sema::applyFunctionAttributesBeforeParsingBody(Decl *FD) {
if (!FD || FD->isInvalidDecl())
return;
if (auto *TD = dyn_cast<FunctionTemplateDecl>(FD))
FD = TD->getTemplatedDecl();
if (FD && FD->hasAttr<OptimizeNoneAttr>()) {
FPOptionsOverride FPO;
FPO.setDisallowOptimizations();
CurFPFeatures.applyChanges(FPO);
FpPragmaStack.CurrentValue =
CurFPFeatures.getChangesFrom(FPOptions(LangOpts));
}
}

/// Given the set of return statements within a function body,
/// compute the variables that are subject to the named return value
/// optimization.
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1302,7 +1302,7 @@ static bool checkTupleLikeDecomposition(Sema &S,
// in the associated namespaces.
Expr *Get = UnresolvedLookupExpr::Create(
S.Context, nullptr, NestedNameSpecifierLoc(), SourceLocation(),
DeclarationNameInfo(GetDN, Loc), /*RequiresADL*/ true, &Args,
DeclarationNameInfo(GetDN, Loc), /*RequiresADL=*/true, &Args,
UnresolvedSetIterator(), UnresolvedSetIterator(),
/*KnownDependent=*/false);

Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Sema/SemaDeclObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,10 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
}
}
}

// Some function attributes (like OptimizeNoneAttr) need actions before
// parsing body started.
applyFunctionAttributesBeforeParsingBody(D);
}

namespace {
Expand Down
45 changes: 14 additions & 31 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2918,26 +2918,9 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
// to get this right here so that we don't end up making a
// spuriously dependent expression if we're inside a dependent
// instance method.
if (getLangOpts().CPlusPlus && !R.empty() &&
(*R.begin())->isCXXClassMember()) {
bool MightBeImplicitMember;
if (!IsAddressOfOperand)
MightBeImplicitMember = true;
else if (!SS.isEmpty())
MightBeImplicitMember = false;
else if (R.isOverloadedResult())
MightBeImplicitMember = false;
else if (R.isUnresolvableResult())
MightBeImplicitMember = true;
else
MightBeImplicitMember = isa<FieldDecl>(R.getFoundDecl()) ||
isa<IndirectFieldDecl>(R.getFoundDecl()) ||
isa<MSPropertyDecl>(R.getFoundDecl());

if (MightBeImplicitMember)
return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc,
R, TemplateArgs, S);
}
if (isPotentialImplicitMemberAccess(SS, R, IsAddressOfOperand))
return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs,
S);

if (TemplateArgs || TemplateKWLoc.isValid()) {

Expand Down Expand Up @@ -3471,12 +3454,10 @@ ExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
// we've picked a target.
R.suppressDiagnostics();

UnresolvedLookupExpr *ULE
= UnresolvedLookupExpr::Create(Context, R.getNamingClass(),
SS.getWithLocInContext(Context),
R.getLookupNameInfo(),
NeedsADL, R.isOverloadedResult(),
R.begin(), R.end());
UnresolvedLookupExpr *ULE = UnresolvedLookupExpr::Create(
Context, R.getNamingClass(), SS.getWithLocInContext(Context),
R.getLookupNameInfo(), NeedsADL, R.begin(), R.end(),
/*KnownDependent=*/false);

return ULE;
}
Expand Down Expand Up @@ -4156,11 +4137,13 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
// 'wb/uwb' literals are a C23 feature. We support _BitInt as a type in C++,
// but we do not currently support the suffix in C++ mode because it's not
// entirely clear whether WG21 will prefer this suffix to return a library
// type such as std::bit_int instead of returning a _BitInt.
if (Literal.isBitInt && !getLangOpts().CPlusPlus)
PP.Diag(Tok.getLocation(), getLangOpts().C23
? diag::warn_c23_compat_bitint_suffix
: diag::ext_c23_bitint_suffix);
// type such as std::bit_int instead of returning a _BitInt. '__wb/__uwb'
// literals are a C++ extension.
if (Literal.isBitInt)
PP.Diag(Tok.getLocation(),
getLangOpts().CPlusPlus ? diag::ext_cxx_bitint_suffix
: getLangOpts().C23 ? diag::warn_c23_compat_bitint_suffix
: diag::ext_c23_bitint_suffix);

// Get the value in the widest-possible width. What is "widest" depends on
// whether the literal is a bit-precise integer or not. For a bit-precise
Expand Down
61 changes: 32 additions & 29 deletions clang/lib/Sema/SemaExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1416,26 +1416,42 @@ bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit,
}

ExprResult Sema::ActOnCXXThis(SourceLocation Loc) {
/// C++ 9.3.2: In the body of a non-static member function, the keyword this
/// is a non-lvalue expression whose value is the address of the object for
/// which the function is called.
// C++20 [expr.prim.this]p1:
// The keyword this names a pointer to the object for which an
// implicit object member function is invoked or a non-static
// data member's initializer is evaluated.
QualType ThisTy = getCurrentThisType();

if (ThisTy.isNull()) {
DeclContext *DC = getFunctionLevelDeclContext();
if (CheckCXXThisType(Loc, ThisTy))
return ExprError();

if (const auto *Method = dyn_cast<CXXMethodDecl>(DC);
Method && Method->isExplicitObjectMemberFunction()) {
return Diag(Loc, diag::err_invalid_this_use) << 1;
}
return BuildCXXThisExpr(Loc, ThisTy, /*IsImplicit=*/false);
}

if (isLambdaCallWithExplicitObjectParameter(CurContext))
return Diag(Loc, diag::err_invalid_this_use) << 1;
bool Sema::CheckCXXThisType(SourceLocation Loc, QualType Type) {
if (!Type.isNull())
return false;

return Diag(Loc, diag::err_invalid_this_use) << 0;
// C++20 [expr.prim.this]p3:
// If a declaration declares a member function or member function template
// of a class X, the expression this is a prvalue of type
// "pointer to cv-qualifier-seq X" wherever X is the current class between
// the optional cv-qualifier-seq and the end of the function-definition,
// member-declarator, or declarator. It shall not appear within the
// declaration of either a static member function or an explicit object
// member function of the current class (although its type and value
// 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()) {
Diag(Loc, diag::err_invalid_this_use) << 1;
} else if (isLambdaCallWithExplicitObjectParameter(CurContext)) {
Diag(Loc, diag::err_invalid_this_use) << 1;
} else {
Diag(Loc, diag::err_invalid_this_use) << 0;
}

return BuildCXXThisExpr(Loc, ThisTy, /*IsImplicit=*/false);
return true;
}

Expr *Sema::BuildCXXThisExpr(SourceLocation Loc, QualType Type,
Expand Down Expand Up @@ -8644,21 +8660,8 @@ static ExprResult attemptRecovery(Sema &SemaRef,

// Detect and handle the case where the decl might be an implicit
// member.
bool MightBeImplicitMember;
if (!Consumer.isAddressOfOperand())
MightBeImplicitMember = true;
else if (!NewSS.isEmpty())
MightBeImplicitMember = false;
else if (R.isOverloadedResult())
MightBeImplicitMember = false;
else if (R.isUnresolvableResult())
MightBeImplicitMember = true;
else
MightBeImplicitMember = isa<FieldDecl>(ND) ||
isa<IndirectFieldDecl>(ND) ||
isa<MSPropertyDecl>(ND);

if (MightBeImplicitMember)
if (SemaRef.isPotentialImplicitMemberAccess(
NewSS, R, Consumer.isAddressOfOperand()))
return SemaRef.BuildPossibleImplicitMemberExpr(
NewSS, /*TemplateKWLoc*/ SourceLocation(), R,
/*TemplateArgs*/ nullptr, /*S*/ nullptr);
Expand Down
72 changes: 57 additions & 15 deletions clang/lib/Sema/SemaExprMember.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ enum IMAKind {
/// The reference is a contextually-permitted abstract member reference.
IMA_Abstract,

/// Whether the context is static is dependent on the enclosing template (i.e.
/// in a dependent class scope explicit specialization).
IMA_Dependent,

/// The reference may be to an unresolved using declaration and the
/// context is not an instance method.
IMA_Unresolved_StaticOrExplicitContext,
Expand Down Expand Up @@ -92,14 +96,25 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,

DeclContext *DC = SemaRef.getFunctionLevelDeclContext();

bool isStaticOrExplicitContext =
SemaRef.CXXThisTypeOverride.isNull() &&
(!isa<CXXMethodDecl>(DC) || cast<CXXMethodDecl>(DC)->isStatic() ||
cast<CXXMethodDecl>(DC)->isExplicitObjectMemberFunction());
bool couldInstantiateToStatic = false;
bool isStaticOrExplicitContext = SemaRef.CXXThisTypeOverride.isNull();

if (R.isUnresolvableResult())
if (auto *MD = dyn_cast<CXXMethodDecl>(DC)) {
if (MD->isImplicitObjectMemberFunction()) {
isStaticOrExplicitContext = false;
// A dependent class scope function template explicit specialization
// that is neither declared 'static' nor with an explicit object
// parameter could instantiate to a static or non-static member function.
couldInstantiateToStatic = MD->getDependentSpecializationInfo();
}
}

if (R.isUnresolvableResult()) {
if (couldInstantiateToStatic)
return IMA_Dependent;
return isStaticOrExplicitContext ? IMA_Unresolved_StaticOrExplicitContext
: IMA_Unresolved;
}

// Collect all the declaring classes of instance members we find.
bool hasNonInstance = false;
Expand All @@ -124,6 +139,9 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
if (Classes.empty())
return IMA_Static;

if (couldInstantiateToStatic)
return IMA_Dependent;

// C++11 [expr.prim.general]p12:
// An id-expression that denotes a non-static data member or non-static
// member function of a class can only be used:
Expand Down Expand Up @@ -264,21 +282,37 @@ static void diagnoseInstanceReference(Sema &SemaRef,
}
}

bool Sema::isPotentialImplicitMemberAccess(const CXXScopeSpec &SS,
LookupResult &R,
bool IsAddressOfOperand) {
if (!getLangOpts().CPlusPlus)
return false;
else if (R.empty() || !R.begin()->isCXXClassMember())
return false;
else if (!IsAddressOfOperand)
return true;
else if (!SS.isEmpty())
return false;
else if (R.isOverloadedResult())
return false;
else if (R.isUnresolvableResult())
return true;
else
return isa<FieldDecl, IndirectFieldDecl, MSPropertyDecl>(R.getFoundDecl());
}

/// Builds an expression which might be an implicit member expression.
ExprResult Sema::BuildPossibleImplicitMemberExpr(
const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs, const Scope *S,
UnresolvedLookupExpr *AsULE) {
switch (ClassifyImplicitMemberAccess(*this, R)) {
const TemplateArgumentListInfo *TemplateArgs, const Scope *S) {
switch (IMAKind Classification = ClassifyImplicitMemberAccess(*this, R)) {
case IMA_Instance:
return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, true, S);

case IMA_Mixed:
case IMA_Mixed_Unrelated:
case IMA_Unresolved:
return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, false,
S);

return BuildImplicitMemberExpr(
SS, TemplateKWLoc, R, TemplateArgs,
/*IsKnownInstance=*/Classification == IMA_Instance, S);
case IMA_Field_Uneval_Context:
Diag(R.getNameLoc(), diag::warn_cxx98_compat_non_static_member_use)
<< R.getLookupNameInfo().getName();
Expand All @@ -288,8 +322,16 @@ ExprResult Sema::BuildPossibleImplicitMemberExpr(
case IMA_Mixed_StaticOrExplicitContext:
case IMA_Unresolved_StaticOrExplicitContext:
if (TemplateArgs || TemplateKWLoc.isValid())
return BuildTemplateIdExpr(SS, TemplateKWLoc, R, false, TemplateArgs);
return AsULE ? AsULE : BuildDeclarationNameExpr(SS, R, false);
return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*RequiresADL=*/false,
TemplateArgs);
return BuildDeclarationNameExpr(SS, R, /*NeedsADL=*/false,
/*AcceptInvalidDecl=*/false);
case IMA_Dependent:
R.suppressDiagnostics();
return UnresolvedLookupExpr::Create(
Context, R.getNamingClass(), SS.getWithLocInContext(Context),
TemplateKWLoc, R.getLookupNameInfo(), /*RequiresADL=*/false,
TemplateArgs, R.begin(), R.end(), /*KnownDependent=*/true);

case IMA_Error_StaticOrExplicitContext:
case IMA_Error_Unrelated:
Expand Down
35 changes: 35 additions & 0 deletions clang/lib/Sema/SemaOpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ bool doesClauseApplyToDirective(OpenACCDirectiveKind DirectiveKind,
default:
return false;
}
case OpenACCClauseKind::NumGangs:
case OpenACCClauseKind::NumWorkers:
case OpenACCClauseKind::VectorLength:
switch (DirectiveKind) {
Expand Down Expand Up @@ -230,6 +231,40 @@ SemaOpenACC::ActOnClause(ArrayRef<const OpenACCClause *> ExistingClauses,
getASTContext(), Clause.getBeginLoc(), Clause.getLParenLoc(),
Clause.getConditionExpr(), Clause.getEndLoc());
}
case OpenACCClauseKind::NumGangs: {
// Restrictions only properly implemented on 'compute' constructs, and
// 'compute' constructs are the only construct that can do anything with
// this yet, so skip/treat as unimplemented in this case.
if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
break;

// There is no prose in the standard that says duplicates aren't allowed,
// but this diagnostic is present in other compilers, as well as makes
// sense.
if (checkAlreadyHasClauseOfKind(*this, ExistingClauses, Clause))
return nullptr;

if (Clause.getIntExprs().empty())
Diag(Clause.getBeginLoc(), diag::err_acc_num_gangs_num_args)
<< /*NoArgs=*/0;

unsigned MaxArgs =
(Clause.getDirectiveKind() == OpenACCDirectiveKind::Parallel ||
Clause.getDirectiveKind() == OpenACCDirectiveKind::ParallelLoop)
? 3
: 1;
if (Clause.getIntExprs().size() > MaxArgs)
Diag(Clause.getBeginLoc(), diag::err_acc_num_gangs_num_args)
<< /*NoArgs=*/1 << Clause.getDirectiveKind() << MaxArgs
<< Clause.getIntExprs().size();

// Create the AST node for the clause even if the number of expressions is
// incorrect.
return OpenACCNumGangsClause::Create(
getASTContext(), Clause.getBeginLoc(), Clause.getLParenLoc(),
Clause.getIntExprs(), Clause.getEndLoc());
break;
}
case OpenACCClauseKind::NumWorkers: {
// Restrictions only properly implemented on 'compute' constructs, and
// 'compute' constructs are the only construct that can do anything with
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Sema/SemaOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19354,7 +19354,7 @@ buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range,
return UnresolvedLookupExpr::Create(
SemaRef.Context, /*NamingClass=*/nullptr,
ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
/*ADL=*/true, /*Overloaded=*/true, ResSet.begin(), ResSet.end());
/*ADL=*/true, ResSet.begin(), ResSet.end(), /*KnownDependent=*/false);
}
// Lookup inside the classes.
// C++ [over.match.oper]p3:
Expand Down Expand Up @@ -22220,7 +22220,7 @@ static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S,
return UnresolvedLookupExpr::Create(
SemaRef.Context, /*NamingClass=*/nullptr,
MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
/*ADL=*/false, /*Overloaded=*/true, URS.begin(), URS.end());
/*ADL=*/false, URS.begin(), URS.end(), /*KnownDependent=*/false);
}
SourceLocation Loc = MapperId.getLoc();
// [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
Expand Down
10 changes: 2 additions & 8 deletions clang/lib/Sema/SemaOverload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14261,20 +14261,14 @@ ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn,
OverloadResult, AllowTypoCorrection);
}

static bool IsOverloaded(const UnresolvedSetImpl &Functions) {
return Functions.size() > 1 ||
(Functions.size() == 1 &&
isa<FunctionTemplateDecl>((*Functions.begin())->getUnderlyingDecl()));
}

ExprResult Sema::CreateUnresolvedLookupExpr(CXXRecordDecl *NamingClass,
NestedNameSpecifierLoc NNSLoc,
DeclarationNameInfo DNI,
const UnresolvedSetImpl &Fns,
bool PerformADL) {
return UnresolvedLookupExpr::Create(Context, NamingClass, NNSLoc, DNI,
PerformADL, IsOverloaded(Fns),
Fns.begin(), Fns.end());
PerformADL, Fns.begin(), Fns.end(),
/*KnownDependent=*/false);
}

ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl,
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaStmtAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
SetHints(LoopHintAttr::Unroll, LoopHintAttr::Disable);
} else if (PragmaName == "unroll") {
// #pragma unroll N
if (ValueExpr) {
if (ValueExpr && !ValueExpr->isValueDependent()) {
llvm::APSInt ValueAPS;
ExprResult R = S.VerifyIntegerConstantExpression(ValueExpr, &ValueAPS);
assert(!R.isInvalid() && "unroll count value must be a valid value, it's "
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5101,6 +5101,14 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
EnterExpressionEvaluationContext EvalContext(
*this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);

Qualifiers ThisTypeQuals;
CXXRecordDecl *ThisContext = nullptr;
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Function)) {
ThisContext = Method->getParent();
ThisTypeQuals = Method->getMethodQualifiers();
}
CXXThisScopeRAII ThisScope(*this, ThisContext, ThisTypeQuals);

// Introduce a new scope where local variable instantiations will be
// recorded, unless we're actually a member function within a local
// class, in which case we need to merge our results with the parent
Expand Down
8 changes: 5 additions & 3 deletions clang/lib/Sema/SemaTemplateVariadic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1085,9 +1085,11 @@ ExprResult Sema::ActOnPackIndexingExpr(Scope *S, Expr *PackExpression,
SourceLocation RSquareLoc) {
bool isParameterPack = ::isParameterPack(PackExpression);
if (!isParameterPack) {
CorrectDelayedTyposInExpr(IndexExpr);
Diag(PackExpression->getBeginLoc(), diag::err_expected_name_of_pack)
<< PackExpression;
if (!PackExpression->containsErrors()) {
CorrectDelayedTyposInExpr(IndexExpr);
Diag(PackExpression->getBeginLoc(), diag::err_expected_name_of_pack)
<< PackExpression;
}
return ExprError();
}
ExprResult Res =
Expand Down
112 changes: 75 additions & 37 deletions clang/lib/Sema/TreeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,9 @@ class TreeTransform {
ParenExpr *PE, DependentScopeDeclRefExpr *DRE, bool IsAddressOfOperand,
TypeSourceInfo **RecoveryTSI);

ExprResult TransformUnresolvedLookupExpr(UnresolvedLookupExpr *E,
bool IsAddressOfOperand);

StmtResult TransformOMPExecutableDirective(OMPExecutableDirective *S);

// FIXME: We use LLVM_ATTRIBUTE_NOINLINE because inlining causes a ridiculous
Expand Down Expand Up @@ -3320,12 +3323,13 @@ class TreeTransform {

/// Build a new C++ "this" expression.
///
/// By default, builds a new "this" expression without performing any
/// semantic analysis. Subclasses may override this routine to provide
/// different behavior.
/// By default, performs semantic analysis to build a new "this" expression.
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildCXXThisExpr(SourceLocation ThisLoc,
QualType ThisType,
bool isImplicit) {
if (getSema().CheckCXXThisType(ThisLoc, ThisType))
return ExprError();
return getSema().BuildCXXThisExpr(ThisLoc, ThisType, isImplicit);
}

Expand Down Expand Up @@ -4759,8 +4763,6 @@ class TemplateArgumentLocInventIterator {
const TemplateArgumentLoc *operator->() const { return &Arg; }
};

TemplateArgumentLocInventIterator() { }

explicit TemplateArgumentLocInventIterator(TreeTransform<Derived> &Self,
InputIterator Iter)
: Self(Self), Iter(Iter) { }
Expand Down Expand Up @@ -10429,12 +10431,11 @@ TreeTransform<Derived>::TransformOMPReductionClause(OMPReductionClause *C) {
cast<NamedDecl>(getDerived().TransformDecl(E->getExprLoc(), D));
Decls.addDecl(InstD, InstD->getAccess());
}
UnresolvedReductions.push_back(
UnresolvedLookupExpr::Create(
UnresolvedReductions.push_back(UnresolvedLookupExpr::Create(
SemaRef.Context, /*NamingClass=*/nullptr,
ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context),
NameInfo, /*ADL=*/true, ULE->isOverloaded(),
Decls.begin(), Decls.end()));
ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), NameInfo,
/*ADL=*/true, Decls.begin(), Decls.end(),
/*KnownDependent=*/false));
} else
UnresolvedReductions.push_back(nullptr);
}
Expand Down Expand Up @@ -10480,7 +10481,8 @@ OMPClause *TreeTransform<Derived>::TransformOMPTaskReductionClause(
UnresolvedReductions.push_back(UnresolvedLookupExpr::Create(
SemaRef.Context, /*NamingClass=*/nullptr,
ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), NameInfo,
/*ADL=*/true, ULE->isOverloaded(), Decls.begin(), Decls.end()));
/*ADL=*/true, Decls.begin(), Decls.end(),
/*KnownDependent=*/false));
} else
UnresolvedReductions.push_back(nullptr);
}
Expand Down Expand Up @@ -10525,7 +10527,8 @@ TreeTransform<Derived>::TransformOMPInReductionClause(OMPInReductionClause *C) {
UnresolvedReductions.push_back(UnresolvedLookupExpr::Create(
SemaRef.Context, /*NamingClass=*/nullptr,
ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), NameInfo,
/*ADL=*/true, ULE->isOverloaded(), Decls.begin(), Decls.end()));
/*ADL=*/true, Decls.begin(), Decls.end(),
/*KnownDependent=*/false));
} else
UnresolvedReductions.push_back(nullptr);
}
Expand Down Expand Up @@ -10706,8 +10709,8 @@ bool transformOMPMappableExprListClause(
UnresolvedMappers.push_back(UnresolvedLookupExpr::Create(
TT.getSema().Context, /*NamingClass=*/nullptr,
MapperIdScopeSpec.getWithLocInContext(TT.getSema().Context),
MapperIdInfo, /*ADL=*/true, ULE->isOverloaded(), Decls.begin(),
Decls.end()));
MapperIdInfo, /*ADL=*/true, Decls.begin(), Decls.end(),
/*KnownDependent=*/false));
} else {
UnresolvedMappers.push_back(nullptr);
}
Expand Down Expand Up @@ -11159,6 +11162,32 @@ void OpenACCClauseTransform<Derived>::VisitSelfClause(
ParsedClause.getEndLoc());
}

template <typename Derived>
void OpenACCClauseTransform<Derived>::VisitNumGangsClause(
const OpenACCNumGangsClause &C) {
llvm::SmallVector<Expr *> InstantiatedIntExprs;

for (Expr *CurIntExpr : C.getIntExprs()) {
ExprResult Res = Self.TransformExpr(CurIntExpr);

if (!Res.isUsable())
return;

Res = Self.getSema().OpenACC().ActOnIntExpr(OpenACCDirectiveKind::Invalid,
C.getClauseKind(),
C.getBeginLoc(), Res.get());
if (!Res.isUsable())
return;

InstantiatedIntExprs.push_back(Res.get());
}

ParsedClause.setIntExprDetails(InstantiatedIntExprs);
NewClause = OpenACCNumGangsClause::Create(
Self.getSema().getASTContext(), ParsedClause.getBeginLoc(),
ParsedClause.getLParenLoc(), ParsedClause.getIntExprs(),
ParsedClause.getEndLoc());
}
template <typename Derived>
void OpenACCClauseTransform<Derived>::VisitNumWorkersClause(
const OpenACCNumWorkersClause &C) {
Expand Down Expand Up @@ -11467,7 +11496,11 @@ template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformAddressOfOperand(Expr *E) {
if (DependentScopeDeclRefExpr *DRE = dyn_cast<DependentScopeDeclRefExpr>(E))
return getDerived().TransformDependentScopeDeclRefExpr(DRE, true, nullptr);
return getDerived().TransformDependentScopeDeclRefExpr(
DRE, /*IsAddressOfOperand=*/true, nullptr);
else if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E))
return getDerived().TransformUnresolvedLookupExpr(
ULE, /*IsAddressOfOperand=*/true);
else
return getDerived().TransformExpr(E);
}
Expand Down Expand Up @@ -13174,10 +13207,16 @@ bool TreeTransform<Derived>::TransformOverloadExprDecls(OverloadExpr *Old,
return false;
}

template<typename Derived>
template <typename Derived>
ExprResult TreeTransform<Derived>::TransformUnresolvedLookupExpr(
UnresolvedLookupExpr *Old) {
return TransformUnresolvedLookupExpr(Old, /*IsAddressOfOperand=*/false);
}

template <typename Derived>
ExprResult
TreeTransform<Derived>::TransformUnresolvedLookupExpr(
UnresolvedLookupExpr *Old) {
TreeTransform<Derived>::TransformUnresolvedLookupExpr(UnresolvedLookupExpr *Old,
bool IsAddressOfOperand) {
LookupResult R(SemaRef, Old->getName(), Old->getNameLoc(),
Sema::LookupOrdinaryName);

Expand Down Expand Up @@ -13209,26 +13248,8 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr(
R.setNamingClass(NamingClass);
}

// Rebuild the template arguments, if any.
SourceLocation TemplateKWLoc = Old->getTemplateKeywordLoc();

// If we have neither explicit template arguments, nor the template keyword,
// it's a normal declaration name or member reference.
if (!Old->hasExplicitTemplateArgs() && !TemplateKWLoc.isValid()) {
NamedDecl *D = R.getAsSingle<NamedDecl>();
// In a C++11 unevaluated context, an UnresolvedLookupExpr might refer to an
// instance member. In other contexts, BuildPossibleImplicitMemberExpr will
// give a good diagnostic.
if (D && D->isCXXInstanceMember()) {
return SemaRef.BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, R,
/*TemplateArgs=*/nullptr,
/*Scope=*/nullptr);
}

return getDerived().RebuildDeclarationNameExpr(SS, R, Old->requiresADL());
}

// If we have template arguments, rebuild them, then rebuild the
// templateid expression.
TemplateArgumentListInfo TransArgs(Old->getLAngleLoc(), Old->getRAngleLoc());
if (Old->hasExplicitTemplateArgs() &&
getDerived().TransformTemplateArguments(Old->getTemplateArgs(),
Expand All @@ -13238,6 +13259,23 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr(
return ExprError();
}

// An UnresolvedLookupExpr can refer to a class member. This occurs e.g. when
// a non-static data member is named in an unevaluated operand, or when
// a member is named in a dependent class scope function template explicit
// specialization that is neither declared static nor with an explicit object
// parameter.
if (SemaRef.isPotentialImplicitMemberAccess(SS, R, IsAddressOfOperand))
return SemaRef.BuildPossibleImplicitMemberExpr(
SS, TemplateKWLoc, R,
Old->hasExplicitTemplateArgs() ? &TransArgs : nullptr,
/*S=*/nullptr);

// If we have neither explicit template arguments, nor the template keyword,
// it's a normal declaration name or member reference.
if (!Old->hasExplicitTemplateArgs() && !TemplateKWLoc.isValid())
return getDerived().RebuildDeclarationNameExpr(SS, R, Old->requiresADL());

// If we have template arguments, then rebuild the template-id expression.
return getDerived().RebuildTemplateIdExpr(SS, TemplateKWLoc, R,
Old->requiresADL(), &TransArgs);
}
Expand Down
246 changes: 131 additions & 115 deletions clang/lib/Serialization/ASTReader.cpp

Large diffs are not rendered by default.

280 changes: 147 additions & 133 deletions clang/lib/Serialization/ASTReaderDecl.cpp

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions clang/lib/Serialization/ASTReaderInternals.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,15 @@ class ASTDeclContextNameLookupTrait {
static const int MaxTables = 4;

/// The lookup result is a list of global declaration IDs.
using data_type = SmallVector<DeclID, 4>;
using data_type = SmallVector<GlobalDeclID, 4>;

struct data_type_builder {
data_type &Data;
llvm::DenseSet<DeclID> Found;
llvm::DenseSet<GlobalDeclID> Found;

data_type_builder(data_type &D) : Data(D) {}

void insert(DeclID ID) {
void insert(GlobalDeclID ID) {
// Just use a linear scan unless we have more than a few IDs.
if (Found.empty() && !Data.empty()) {
if (Data.size() <= 4) {
Expand Down Expand Up @@ -108,7 +108,7 @@ class ASTDeclContextNameLookupTrait {

static void MergeDataInto(const data_type &From, data_type_builder &To) {
To.Data.reserve(To.Data.size() + From.size());
for (DeclID ID : From)
for (GlobalDeclID ID : From)
To.insert(ID);
}

Expand Down
1 change: 0 additions & 1 deletion clang/lib/Serialization/ASTReaderStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2096,7 +2096,6 @@ void ASTStmtReader::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) {
void ASTStmtReader::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
VisitOverloadExpr(E);
E->UnresolvedLookupExprBits.RequiresADL = CurrentUnpackingBits->getNextBit();
E->UnresolvedLookupExprBits.Overloaded = CurrentUnpackingBits->getNextBit();
E->NamingClass = readDeclAs<CXXRecordDecl>();
}

Expand Down
35 changes: 22 additions & 13 deletions clang/lib/Serialization/ASTWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3210,7 +3210,7 @@ uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context,
return 0;

uint64_t Offset = Stream.GetCurrentBitNo();
SmallVector<uint32_t, 128> KindDeclPairs;
SmallVector<DeclID, 128> KindDeclPairs;
for (const auto *D : DC->decls()) {
if (DoneWritingDeclsAndTypes && !wasDeclEmitted(D))
continue;
Expand Down Expand Up @@ -3348,11 +3348,11 @@ class ASTMethodPoolTrait {
for (const ObjCMethodList *Method = &Methods.Instance; Method;
Method = Method->getNext())
if (ShouldWriteMethodListNode(Method))
DataLen += 4;
DataLen += sizeof(DeclID);
for (const ObjCMethodList *Method = &Methods.Factory; Method;
Method = Method->getNext())
if (ShouldWriteMethodListNode(Method))
DataLen += 4;
DataLen += sizeof(DeclID);
return emitULEBKeyDataLength(KeyLen, DataLen, Out);
}

Expand Down Expand Up @@ -3410,11 +3410,11 @@ class ASTMethodPoolTrait {
for (const ObjCMethodList *Method = &Methods.Instance; Method;
Method = Method->getNext())
if (ShouldWriteMethodListNode(Method))
LE.write<uint32_t>(Writer.getDeclID(Method->getMethod()));
LE.write<DeclID>(Writer.getDeclID(Method->getMethod()));
for (const ObjCMethodList *Method = &Methods.Factory; Method;
Method = Method->getNext())
if (ShouldWriteMethodListNode(Method))
LE.write<uint32_t>(Writer.getDeclID(Method->getMethod()));
LE.write<DeclID>(Writer.getDeclID(Method->getMethod()));

assert(Out.tell() - Start == DataLen && "Data length is wrong");
}
Expand Down Expand Up @@ -3687,7 +3687,8 @@ class ASTIdentifierTableTrait {
DataLen += 4; // MacroDirectives offset.

if (NeedDecls)
DataLen += std::distance(IdResolver.begin(II), IdResolver.end()) * 4;
DataLen += std::distance(IdResolver.begin(II), IdResolver.end()) *
sizeof(DeclID);
}
return emitULEBKeyDataLength(KeyLen, DataLen, Out);
}
Expand Down Expand Up @@ -3733,7 +3734,7 @@ class ASTIdentifierTableTrait {
// Only emit declarations that aren't from a chained PCH, though.
SmallVector<NamedDecl *, 16> Decls(IdResolver.decls(II));
for (NamedDecl *D : llvm::reverse(Decls))
LE.write<uint32_t>(
LE.write<DeclID>(
Writer.getDeclID(getDeclForLocalLookup(PP.getLangOpts(), D)));
}
}
Expand Down Expand Up @@ -3883,7 +3884,8 @@ class ASTDeclContextNameLookupTrait {

data_type ImportData(const reader::ASTDeclContextNameLookupTrait::data_type &FromReader) {
unsigned Start = DeclIDs.size();
llvm::append_range(DeclIDs, FromReader);
DeclIDs.insert(DeclIDs.end(), DeclIDIterator(FromReader.begin()),
DeclIDIterator(FromReader.end()));
return std::make_pair(Start, DeclIDs.size());
}

Expand Down Expand Up @@ -3928,8 +3930,8 @@ class ASTDeclContextNameLookupTrait {
break;
}

// 4 bytes for each DeclID.
unsigned DataLen = 4 * (Lookup.second - Lookup.first);
// length of DeclIDs.
unsigned DataLen = sizeof(DeclID) * (Lookup.second - Lookup.first);

return emitULEBKeyDataLength(KeyLen, DataLen, Out);
}
Expand Down Expand Up @@ -3972,7 +3974,7 @@ class ASTDeclContextNameLookupTrait {
endian::Writer LE(Out, llvm::endianness::little);
uint64_t Start = Out.tell(); (void)Start;
for (unsigned I = Lookup.first, N = Lookup.second; I != N; ++I)
LE.write<uint32_t>(DeclIDs[I]);
LE.write<DeclID>(DeclIDs[I]);
assert(Out.tell() - Start == DataLen && "Data length is wrong");
}
};
Expand Down Expand Up @@ -5486,7 +5488,7 @@ void ASTWriter::WriteDeclAndTypes(ASTContext &Context) {
const TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
// Create a lexical update block containing all of the declarations in the
// translation unit that do not come from other AST files.
SmallVector<uint32_t, 128> NewGlobalKindDeclPairs;
SmallVector<DeclID, 128> NewGlobalKindDeclPairs;
for (const auto *D : TU->noload_decls()) {
if (D->isFromASTFile())
continue;
Expand Down Expand Up @@ -7657,6 +7659,14 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {
AddStmt(const_cast<Expr *>(SC->getConditionExpr()));
return;
}
case OpenACCClauseKind::NumGangs: {
const auto *NGC = cast<OpenACCNumGangsClause>(C);
writeSourceLocation(NGC->getLParenLoc());
writeUInt32(NGC->getIntExprs().size());
for (Expr *E : NGC->getIntExprs())
AddStmt(E);
return;
}
case OpenACCClauseKind::NumWorkers: {
const auto *NWC = cast<OpenACCNumWorkersClause>(C);
writeSourceLocation(NWC->getLParenLoc());
Expand Down Expand Up @@ -7697,7 +7707,6 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {
case OpenACCClauseKind::Reduction:
case OpenACCClauseKind::Collapse:
case OpenACCClauseKind::Bind:
case OpenACCClauseKind::NumGangs:
case OpenACCClauseKind::DeviceNum:
case OpenACCClauseKind::DefaultAsync:
case OpenACCClauseKind::DeviceType:
Expand Down
1 change: 0 additions & 1 deletion clang/lib/Serialization/ASTWriterStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2082,7 +2082,6 @@ void ASTStmtWriter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) {
void ASTStmtWriter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
VisitOverloadExpr(E);
CurrentPackingBits.addBit(E->requiresADL());
CurrentPackingBits.addBit(E->isOverloaded());
Record.AddDeclRef(E->getNamingClass());
Code = serialization::EXPR_CXX_UNRESOLVED_LOOKUP;
}
Expand Down
14 changes: 6 additions & 8 deletions clang/lib/StaticAnalyzer/Checkers/Taint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,21 +216,17 @@ std::vector<SymbolRef> taint::getTaintedSymbolsImpl(ProgramStateRef State,
std::vector<SymbolRef> TaintedSymbols;
if (!Reg)
return TaintedSymbols;
// Element region (array element) is tainted if either the base or the offset
// are tainted.

// Element region (array element) is tainted if the offset is tainted.
if (const ElementRegion *ER = dyn_cast<ElementRegion>(Reg)) {
std::vector<SymbolRef> TaintedIndex =
getTaintedSymbolsImpl(State, ER->getIndex(), K, returnFirstOnly);
llvm::append_range(TaintedSymbols, TaintedIndex);
if (returnFirstOnly && !TaintedSymbols.empty())
return TaintedSymbols; // return early if needed
std::vector<SymbolRef> TaintedSuperRegion =
getTaintedSymbolsImpl(State, ER->getSuperRegion(), K, returnFirstOnly);
llvm::append_range(TaintedSymbols, TaintedSuperRegion);
if (returnFirstOnly && !TaintedSymbols.empty())
return TaintedSymbols; // return early if needed
}

// Symbolic region is tainted if the corresponding symbol is tainted.
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(Reg)) {
std::vector<SymbolRef> TaintedRegions =
getTaintedSymbolsImpl(State, SR->getSymbol(), K, returnFirstOnly);
Expand All @@ -239,6 +235,8 @@ std::vector<SymbolRef> taint::getTaintedSymbolsImpl(ProgramStateRef State,
return TaintedSymbols; // return early if needed
}

// Any subregion (including Element and Symbolic regions) is tainted if its
// super-region is tainted.
if (const SubRegion *ER = dyn_cast<SubRegion>(Reg)) {
std::vector<SymbolRef> TaintedSubRegions =
getTaintedSymbolsImpl(State, ER->getSuperRegion(), K, returnFirstOnly);
Expand Down Expand Up @@ -318,4 +316,4 @@ std::vector<SymbolRef> taint::getTaintedSymbolsImpl(ProgramStateRef State,
}
}
return TaintedSymbols;
}
}
6 changes: 6 additions & 0 deletions clang/test/AST/Interp/builtin-functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -633,3 +633,9 @@ void test7(void) {
X = CFSTR("foo", "bar"); // both-error {{too many arguments to function call}}
#endif
}

/// The actual value on my machine is 22, but I have a feeling this will be different
/// on other targets, so just checking for != 0 here. Light testing is fine since
/// the actual implementation uses analyze_os_log::computeOSLogBufferLayout(), which
/// is tested elsewhere.
static_assert(__builtin_os_log_format_buffer_size("%{mask.xyz}s", "abc") != 0, "");
6 changes: 6 additions & 0 deletions clang/test/AST/Interp/c.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,3 +257,9 @@ int Y __attribute__((annotate(
42,
(struct TestStruct) { .a = 1, .b = 2 }
)));

#ifdef __SIZEOF_INT128__
const int *p = &b;
const __int128 K = (__int128)(int*)0;
const unsigned __int128 KU = (unsigned __int128)(int*)0;
#endif
12 changes: 12 additions & 0 deletions clang/test/AST/Interp/literals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1209,4 +1209,16 @@ constexpr int externvar1() { // both-error {{never produces a constant expressio
namespace Extern {
constexpr extern char Oops = 1;
static_assert(Oops == 1, "");

#if __cplusplus >= 201402L
struct NonLiteral {
NonLiteral() {}
};
NonLiteral nl;
constexpr NonLiteral &ExternNonLiteralVarDecl() {
extern NonLiteral nl;
return nl;
}
static_assert(&ExternNonLiteralVarDecl() == &nl, "");
#endif
}
20 changes: 20 additions & 0 deletions clang/test/AST/Interp/vectors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ static_assert(A[1] == 2, ""); // ref-error {{not an integral constant expression
static_assert(A[2] == 3, ""); // ref-error {{not an integral constant expression}}
static_assert(A[3] == 4, ""); // ref-error {{not an integral constant expression}}


/// FIXME: It would be nice if the note said 'vector' instead of 'array'.
static_assert(A[12] == 4, ""); // ref-error {{not an integral constant expression}} \
// expected-error {{not an integral constant expression}} \
// expected-note {{cannot refer to element 12 of array of 4 elements in a constant expression}}


/// VectorSplat casts
typedef __attribute__(( ext_vector_type(4) )) float float4;
constexpr float4 vec4_0 = (float4)0.5f;
Expand All @@ -18,6 +25,19 @@ static_assert(vec4_0[3] == 0.5, ""); // ref-error {{not an integral constant exp
constexpr int vec4_0_discarded = ((float4)12.0f, 0);


/// ImplicitValueInitExpr of vector type
constexpr float4 arr4[2] = {
{1,2,3,4},
};
static_assert(arr4[0][0] == 1, ""); // ref-error {{not an integral constant expression}}
static_assert(arr4[0][1] == 2, ""); // ref-error {{not an integral constant expression}}
static_assert(arr4[0][2] == 3, ""); // ref-error {{not an integral constant expression}}
static_assert(arr4[0][3] == 4, ""); // ref-error {{not an integral constant expression}}
static_assert(arr4[1][0] == 0, ""); // ref-error {{not an integral constant expression}}
static_assert(arr4[1][0] == 0, ""); // ref-error {{not an integral constant expression}}
static_assert(arr4[1][0] == 0, ""); // ref-error {{not an integral constant expression}}
static_assert(arr4[1][0] == 0, ""); // ref-error {{not an integral constant expression}}


/// From constant-expression-cxx11.cpp
namespace Vector {
Expand Down
68 changes: 65 additions & 3 deletions clang/test/AST/ast-dump-fpfeatures.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Test without serialization:
// RUN: %clang_cc1 -fsyntax-only -triple x86_64-pc-linux -std=c++11 -ast-dump %s \
// RUN: %clang_cc1 -fsyntax-only -triple x86_64-pc-linux -std=c++11 -fcxx-exceptions -ast-dump %s \
// RUN: | FileCheck --strict-whitespace %s

// Test with serialization:
// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-pch -o %t %s
// RUN: %clang_cc1 -x c++ -triple x86_64-pc-linux -include-pch %t -ast-dump-all /dev/null \
// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-pch -fcxx-exceptions -o %t %s
// RUN: %clang_cc1 -x c++ -triple x86_64-pc-linux -include-pch %t -fcxx-exceptions -ast-dump-all /dev/null \
// RUN: | sed -e "s/ <undeserialized declarations>//" -e "s/ imported//" \
// RUN: | FileCheck --strict-whitespace %s

Expand Down Expand Up @@ -187,3 +187,65 @@ float func_18(float x, float y) {
// CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward
// CHECK: ReturnStmt
// CHECK: BinaryOperator {{.*}} ConstRoundingMode=downward

#pragma float_control(precise, off)

__attribute__((optnone))
float func_19(float x, float y) {
return x + y;
}

// CHECK-LABEL: FunctionDecl {{.*}} func_19 'float (float, float)'
// CHECK: CompoundStmt {{.*}} MathErrno=1
// CHECK: ReturnStmt
// CHECK: BinaryOperator {{.*}} 'float' '+' ConstRoundingMode=downward MathErrno=1

__attribute__((optnone))
float func_20(float x, float y) try {
return x + y;
} catch (...) {
return 1.0;
}

// CHECK-LABEL: FunctionDecl {{.*}} func_20 'float (float, float)'
// CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward MathErrno=1
// CHECK: ReturnStmt
// CHECK: BinaryOperator {{.*}} 'float' '+' ConstRoundingMode=downward MathErrno=1

struct C21 {
C21(float x, float y);
__attribute__((optnone)) float a_method(float x, float y) {
return x * y;
}
float member;
};

// CHECK-LABEL: CXXMethodDecl {{.*}} a_method 'float (float, float)'
// CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward MathErrno=1
// CHECK: ReturnStmt
// CHECK: BinaryOperator {{.*}} 'float' '*' ConstRoundingMode=downward MathErrno=1

__attribute__((optnone)) C21::C21(float x, float y) : member(x + y) {}

// CHECK-LABEL: CXXConstructorDecl {{.*}} C21 'void (float, float)'
// CHECK: CXXCtorInitializer {{.*}} 'member' 'float'
// CHECK: BinaryOperator {{.*}} 'float' '+' ConstRoundingMode=downward MathErrno=1

template <typename T>
__attribute__((optnone)) T func_22(T x, T y) {
return x + y;
}

// CHECK-LABEL: FunctionTemplateDecl {{.*}} func_22
// CHECK: FunctionDecl {{.*}} func_22 'T (T, T)'
// CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward MathErrno=1
// CHECK: ReturnStmt
// CHECK: BinaryOperator {{.*}} '+' ConstRoundingMode=downward MathErrno=1
// CHECK: FunctionDecl {{.*}} func_22 'float (float, float)'
// CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward MathErrno=1
// CHECK: ReturnStmt
// CHECK: BinaryOperator {{.*}} 'float' '+' ConstRoundingMode=downward MathErrno=1

float func_23(float x, float y) {
return func_22(x, y);
}
29 changes: 29 additions & 0 deletions clang/test/AST/ast-dump-fpfeatures.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Test without serialization:
// RUN: %clang_cc1 -fsyntax-only -triple x86_64-pc-linux -ast-dump %s \
// RUN: | FileCheck --strict-whitespace %s

// Test with serialization:
// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-pch -o %t %s
// RUN: %clang_cc1 -x objective-c -triple x86_64-pc-linux -include-pch %t -ast-dump-all /dev/null \
// RUN: | sed -e "s/ <undeserialized declarations>//" -e "s/ imported//" \
// RUN: | FileCheck --strict-whitespace %s


@interface Adder
- (float) sum: (float)x with: (float)y __attribute((optnone));
@end

#pragma float_control(precise, off)

@implementation Adder
- (float) sum: (float)x with: (float)y __attribute((optnone)) {
return x + y;
}

@end

// CHECK-LABEL: ObjCImplementationDecl {{.*}} Adder
// CHECK: ObjCMethodDecl {{.*}} - sum:with: 'float'
// CHECK: CompoundStmt {{.*}} MathErrno=1
// CHECK-NEXT: ReturnStmt
// CHECK-NEXT: BinaryOperator {{.*}} 'float' '+' MathErrno=1
24 changes: 24 additions & 0 deletions clang/test/AST/ast-dump-late-parsing.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// RUN: %clang_cc1 -fsyntax-only -triple x86_64-pc-linux -std=c++11 -fcxx-exceptions -fdelayed-template-parsing -ast-dump %s \
// RUN: | FileCheck %s

#pragma STDC FENV_ROUND FE_DOWNWARD
#pragma float_control(precise, off)

template <typename T>
__attribute__((optnone)) T func_22(T x, T y) {
return x + y;
}

// CHECK-LABEL: FunctionTemplateDecl {{.*}} func_22
// CHECK: FunctionDecl {{.*}} func_22 'T (T, T)'
// CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward MathErrno=1
// CHECK: ReturnStmt
// CHECK: BinaryOperator {{.*}} '+' ConstRoundingMode=downward MathErrno=1
// CHECK: FunctionDecl {{.*}} func_22 'float (float, float)'
// CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward MathErrno=1
// CHECK: ReturnStmt
// CHECK: BinaryOperator {{.*}} 'float' '+' ConstRoundingMode=downward MathErrno=1

float func_23(float x, float y) {
return func_22(x, y);
}
40 changes: 38 additions & 2 deletions clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2725,7 +2725,25 @@ int main()
// CHECK-NEXT: "type": {
// CHECK-NEXT: "qualType": "bool"
// CHECK-NEXT: },
// CHECK-NEXT: "valueCategory": "prvalue"
// CHECK-NEXT: "valueCategory": "prvalue",
// CHECK-NEXT: "inner": [
// CHECK-NEXT: {
// CHECK-NEXT: "id": "0x{{.*}}",
// CHECK-NEXT: "kind": "TemplateTypeParmType",
// CHECK-NEXT: "type": {
// CHECK-NEXT: "qualType": "_Ty"
// CHECK-NEXT: },
// CHECK-NEXT: "isDependent": true,
// CHECK-NEXT: "isInstantiationDependent": true,
// CHECK-NEXT: "depth": 0,
// CHECK-NEXT: "index": 0,
// CHECK-NEXT: "decl": {
// CHECK-NEXT: "id": "0x{{.*}}",
// CHECK-NEXT: "kind": "TemplateTypeParmDecl",
// CHECK-NEXT: "name": "_Ty"
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
Expand Down Expand Up @@ -3003,7 +3021,25 @@ int main()
// CHECK-NEXT: "type": {
// CHECK-NEXT: "qualType": "bool"
// CHECK-NEXT: },
// CHECK-NEXT: "valueCategory": "prvalue"
// CHECK-NEXT: "valueCategory": "prvalue",
// CHECK-NEXT: "inner": [
// CHECK-NEXT: {
// CHECK-NEXT: "id": "0x{{.*}}",
// CHECK-NEXT: "kind": "TemplateTypeParmType",
// CHECK-NEXT: "type": {
// CHECK-NEXT: "qualType": "_Ty"
// CHECK-NEXT: },
// CHECK-NEXT: "isDependent": true,
// CHECK-NEXT: "isInstantiationDependent": true,
// CHECK-NEXT: "depth": 0,
// CHECK-NEXT: "index": 0,
// CHECK-NEXT: "decl": {
// CHECK-NEXT: "id": "0x{{.*}}",
// CHECK-NEXT: "kind": "TemplateTypeParmDecl",
// CHECK-NEXT: "name": "_Ty"
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
Expand Down
9 changes: 9 additions & 0 deletions clang/test/AST/ast-dump-traits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,19 @@ void test_unary_expr_or_type_trait() {
// CHECK-NEXT: | | `-EnumDecl {{.*}} <col:3, col:11> col:8{{( imported)?}} referenced E
// CHECK-NEXT: | |-CStyleCastExpr {{.*}} <line:13:3, col:21> 'void' <ToVoid>
// CHECK-NEXT: | | `-TypeTraitExpr {{.*}} <col:10, col:21> 'bool' __is_enum
// CHECK-NEXT: | | `-ElaboratedType {{.*}} 'E' sugar
// CHECK-NEXT: | | `-EnumType {{.*}} 'E'
// CHECK-NEXT: | | `-Enum {{.*}} 'E'
// CHECK-NEXT: | |-CStyleCastExpr {{.*}} <line:15:3, col:30> 'void' <ToVoid>
// CHECK-NEXT: | | `-TypeTraitExpr {{.*}} <col:10, col:30> 'bool' __is_same
// CHECK-NEXT: | | |-BuiltinType {{.*}} 'int'
// CHECK-NEXT: | | `-BuiltinType {{.*}} 'float'
// CHECK-NEXT: | `-CStyleCastExpr {{.*}} <line:17:3, col:47> 'void' <ToVoid>
// CHECK-NEXT: | `-TypeTraitExpr {{.*}} <col:10, col:47> 'bool' __is_constructible
// CHECK-NEXT: |-BuiltinType {{.*}} 'int'
// CHECK-NEXT: |-BuiltinType {{.*}} 'int'
// CHECK-NEXT: |-BuiltinType {{.*}} 'int'
// CHECK-NEXT: `-BuiltinType {{.*}} 'int'
// CHECK-NEXT: |-FunctionDecl {{.*}} <line:20:1, line:23:1> line:20:6{{( imported)?}} test_array_type_trait 'void ()'
// CHECK-NEXT: | `-CompoundStmt {{.*}} <col:30, line:23:1>
// CHECK-NEXT: | `-CStyleCastExpr {{.*}} <line:22:3, col:34> 'void' <ToVoid>
Expand Down
32 changes: 32 additions & 0 deletions clang/test/AST/bitint-suffix.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// RUN: %clang_cc1 -ast-dump -Wno-unused %s | FileCheck --strict-whitespace %s

// CHECK: FunctionDecl 0x{{[^ ]*}} <{{.*}}:[[@LINE+1]]:1, line:{{[0-9]*}}:1> line:[[@LINE+1]]:6 func 'void ()'
void func() {
// Ensure that we calculate the correct type from the literal suffix.

// Note: 0__wb should create an _BitInt(2) because a signed bit-precise
// integer requires one bit for the sign and one bit for the value,
// at a minimum.
// CHECK: TypedefDecl 0x{{[^ ]*}} <col:3, col:29> col:29 zero_wb 'typeof (0wb)':'_BitInt(2)'
typedef __typeof__(0__wb) zero_wb;
// CHECK: TypedefDecl 0x{{[^ ]*}} <col:3, col:30> col:30 neg_zero_wb 'typeof (-0wb)':'_BitInt(2)'
typedef __typeof__(-0__wb) neg_zero_wb;
// CHECK: TypedefDecl 0x{{[^ ]*}} <col:3, col:29> col:29 one_wb 'typeof (1wb)':'_BitInt(2)'
typedef __typeof__(1__wb) one_wb;
// CHECK: TypedefDecl 0x{{[^ ]*}} <col:3, col:30> col:30 neg_one_wb 'typeof (-1wb)':'_BitInt(2)'
typedef __typeof__(-1__wb) neg_one_wb;

// CHECK: TypedefDecl 0x{{[^ ]*}} <col:3, col:30> col:30 zero_uwb 'typeof (0uwb)':'unsigned _BitInt(1)'
typedef __typeof__(0__uwb) zero_uwb;
// CHECK: TypedefDecl 0x{{[^ ]*}} <col:3, col:31> col:31 neg_zero_uwb 'typeof (-0uwb)':'unsigned _BitInt(1)'
typedef __typeof__(-0__uwb) neg_zero_uwb;
// CHECK: TypedefDecl 0x{{[^ ]*}} <col:3, col:30> col:30 one_uwb 'typeof (1uwb)':'unsigned _BitInt(1)'
typedef __typeof__(1__uwb) one_uwb;

// Try a value that is too large to fit in [u]intmax_t.

// CHECK: TypedefDecl 0x{{[^ ]*}} <col:3, col:49> col:49 huge_uwb 'typeof (18446744073709551616uwb)':'unsigned _BitInt(65)'
typedef __typeof__(18446744073709551616__uwb) huge_uwb;
// CHECK: TypedefDecl 0x{{[^ ]*}} <col:3, col:48> col:48 huge_wb 'typeof (18446744073709551616wb)':'_BitInt(66)'
typedef __typeof__(18446744073709551616__wb) huge_wb;
}
2 changes: 1 addition & 1 deletion clang/test/CodeGen/PowerPC/builtins-ppc-htm.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// REQUIRES: powerpc-registered-target
// RUN: %clang_cc1 -target-feature +altivec -target-feature +htm -triple powerpc64-unknown-unknown -emit-llvm %s -o - | FileCheck %s
// RUN: not %clang_cc1 -target-feature +altivec -target-feature -htm -triple powerpc64-unknown-unknown -emit-llvm %s 2>&1 | FileCheck %s --check-prefix=ERROR
// RUN: not %clang_cc1 -target-feature +altivec -target-feature -htm -triple powerpc64-unknown-unknown -emit-llvm-only %s 2>&1 | FileCheck %s --check-prefix=ERROR

void test1(long int *r, int code, long int *a, long int *b) {
// CHECK-LABEL: define{{.*}} void @test1
Expand Down
12 changes: 6 additions & 6 deletions clang/test/CodeGen/PowerPC/builtins-ppc-vec-ins-error.c
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
// REQUIRES: powerpc-registered-target

// RUN: %clang_cc1 -flax-vector-conversions=none -target-feature +vsx -target-cpu pwr10 -fsyntax-only \
// RUN: -triple powerpc64le-unknown-unknown -emit-llvm -ferror-limit 10 %s -verify -D __TEST_ELT_SI
// RUN: -triple powerpc64le-unknown-unknown -emit-llvm-only -ferror-limit 10 %s -verify -D __TEST_ELT_SI
// RUN: %clang_cc1 -flax-vector-conversions=none -target-feature +vsx -target-cpu pwr10 -fsyntax-only \
// RUN: -triple powerpc64-unknown-unknown -emit-llvm -ferror-limit 10 %s -verify -D __TEST_ELT_F
// RUN: -triple powerpc64-unknown-unknown -emit-llvm-only -ferror-limit 10 %s -verify -D __TEST_ELT_F
// RUN: %clang_cc1 -flax-vector-conversions=none -target-feature +vsx -target-cpu pwr10 -fsyntax-only \
// RUN: -triple powerpc64le-unknown-unknown -emit-llvm -ferror-limit 10 %s -verify -D __TEST_ELT_SLL
// RUN: -triple powerpc64le-unknown-unknown -emit-llvm-only -ferror-limit 10 %s -verify -D __TEST_ELT_SLL
// RUN: %clang_cc1 -flax-vector-conversions=none -target-feature +vsx -target-cpu pwr10 -fsyntax-only \
// RUN: -triple powerpc64-unknown-unknown -emit-llvm -ferror-limit 10 %s -verify -D __TEST_ELT_D
// RUN: -triple powerpc64-unknown-unknown -emit-llvm-only -ferror-limit 10 %s -verify -D __TEST_ELT_D
// RUN: %clang_cc1 -flax-vector-conversions=none -target-feature +vsx -target-cpu pwr10 -fsyntax-only \
// RUN: -triple powerpc64le-unknown-unknown -emit-llvm -ferror-limit 10 %s -verify -D __TEST_UNALIGNED_UI
// RUN: -triple powerpc64le-unknown-unknown -emit-llvm-only -ferror-limit 10 %s -verify -D __TEST_UNALIGNED_UI
// RUN: %clang_cc1 -flax-vector-conversions=none -target-feature +vsx -target-cpu pwr10 -fsyntax-only \
// RUN: -triple powerpc64-unknown-unknown -emit-llvm -ferror-limit 10 %s -verify
// RUN: -triple powerpc64-unknown-unknown -emit-llvm-only -ferror-limit 10 %s -verify

#include <altivec.h>

Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGen/RISCV/riscv-func-attr-target-err.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// REQUIRES: riscv-registered-target
// RUN: not %clang_cc1 -triple riscv64 -target-feature +zifencei -target-feature +m -target-feature +a \
// RUN: -emit-llvm %s 2>&1 | FileCheck %s
// RUN: -emit-llvm-only %s 2>&1 | FileCheck %s

#include <riscv_vector.h>

Expand Down
12 changes: 6 additions & 6 deletions clang/test/CodeGenCoroutines/coro-await.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ extern "C" void f0() {
// ---------------------------
// Call coro.await.suspend
// ---------------------------
// CHECK-NEXT: call void @llvm.coro.await.suspend.void(ptr %[[AWAITABLE]], ptr %[[FRAME]], ptr @__await_suspend_wrapper_f0_await)
// CHECK-NEXT: call void @llvm.coro.await.suspend.void(ptr %[[AWAITABLE]], ptr %[[FRAME]], ptr @f0.__await_suspend_wrapper__await)
// -------------------------
// Generate a suspend point:
// -------------------------
Expand All @@ -100,7 +100,7 @@ extern "C" void f0() {
// CHECK: call i8 @llvm.coro.suspend(token %[[FINALSP_ID]], i1 true)

// Await suspend wrapper
// CHECK: define{{.*}} @__await_suspend_wrapper_f0_await(ptr {{[^,]*}} %[[AWAITABLE_ARG:.+]], ptr {{[^,]*}} %[[FRAME_ARG:.+]])
// CHECK: define{{.*}} @f0.__await_suspend_wrapper__await(ptr {{[^,]*}} %[[AWAITABLE_ARG:.+]], ptr {{[^,]*}} %[[FRAME_ARG:.+]])
// CHECK: store ptr %[[AWAITABLE_ARG]], ptr %[[AWAITABLE_TMP:.+]],
// CHECK: store ptr %[[FRAME_ARG]], ptr %[[FRAME_TMP:.+]],
// CHECK: %[[AWAITABLE:.+]] = load ptr, ptr %[[AWAITABLE_TMP]]
Expand Down Expand Up @@ -149,7 +149,7 @@ extern "C" void f1(int) {
// ---------------------------
// Call coro.await.suspend
// ---------------------------
// CHECK-NEXT: %[[YES:.+]] = call i1 @llvm.coro.await.suspend.bool(ptr %[[AWAITABLE]], ptr %[[FRAME]], ptr @__await_suspend_wrapper_f1_yield)
// CHECK-NEXT: %[[YES:.+]] = call i1 @llvm.coro.await.suspend.bool(ptr %[[AWAITABLE]], ptr %[[FRAME]], ptr @f1.__await_suspend_wrapper__yield)
// -------------------------------------------
// See if await_suspend decided not to suspend
// -------------------------------------------
Expand All @@ -162,7 +162,7 @@ extern "C" void f1(int) {
// CHECK: call void @_ZN13suspend_maybe12await_resumeEv(ptr {{[^,]*}} %[[AWAITABLE]])

// Await suspend wrapper
// CHECK: define {{.*}} i1 @__await_suspend_wrapper_f1_yield(ptr {{[^,]*}} %[[AWAITABLE_ARG:.+]], ptr {{[^,]*}} %[[FRAME_ARG:.+]])
// CHECK: define {{.*}} i1 @f1.__await_suspend_wrapper__yield(ptr {{[^,]*}} %[[AWAITABLE_ARG:.+]], ptr {{[^,]*}} %[[FRAME_ARG:.+]])
// CHECK: store ptr %[[AWAITABLE_ARG]], ptr %[[AWAITABLE_TMP:.+]],
// CHECK: store ptr %[[FRAME_ARG]], ptr %[[FRAME_TMP:.+]],
// CHECK: %[[AWAITABLE:.+]] = load ptr, ptr %[[AWAITABLE_TMP]]
Expand Down Expand Up @@ -370,7 +370,7 @@ extern "C" void TestTailcall() {
// ---------------------------
// Call coro.await.suspend
// ---------------------------
// CHECK-NEXT: %[[RESUMED:.+]] = call ptr @llvm.coro.await.suspend.handle(ptr %[[AWAITABLE]], ptr %[[FRAME]], ptr @__await_suspend_wrapper_TestTailcall_await)
// CHECK-NEXT: %[[RESUMED:.+]] = call ptr @llvm.coro.await.suspend.handle(ptr %[[AWAITABLE]], ptr %[[FRAME]], ptr @TestTailcall.__await_suspend_wrapper__await)
// CHECK-NEXT: call void @llvm.coro.resume(ptr %[[RESUMED]])
// CHECK-NEXT: %[[OUTCOME:.+]] = call i8 @llvm.coro.suspend(token %[[SUSPEND_ID]], i1 false)
// CHECK-NEXT: switch i8 %[[OUTCOME]], label %[[RET_BB:.+]] [
Expand All @@ -379,7 +379,7 @@ extern "C" void TestTailcall() {
// CHECK-NEXT: ]

// Await suspend wrapper
// CHECK: define {{.*}} ptr @__await_suspend_wrapper_TestTailcall_await(ptr {{[^,]*}} %[[AWAITABLE_ARG:.+]], ptr {{[^,]*}} %[[FRAME_ARG:.+]])
// CHECK: define {{.*}} ptr @TestTailcall.__await_suspend_wrapper__await(ptr {{[^,]*}} %[[AWAITABLE_ARG:.+]], ptr {{[^,]*}} %[[FRAME_ARG:.+]])
// CHECK: store ptr %[[AWAITABLE_ARG]], ptr %[[AWAITABLE_TMP:.+]],
// CHECK: store ptr %[[FRAME_ARG]], ptr %[[FRAME_TMP:.+]],
// CHECK: %[[AWAITABLE:.+]] = load ptr, ptr %[[AWAITABLE_TMP]]
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGenCoroutines/coro-dwarf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,14 @@ void f_coro(int val, MoveOnly moParam, MoveAndCopy mcParam) {
// CHECK: !{{[0-9]+}} = !DILocalVariable(name: "mcParam", arg: 3, scope: ![[SP]], file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}})
// CHECK: !{{[0-9]+}} = !DILocalVariable(name: "__promise",

// CHECK: !{{[0-9]+}} = distinct !DISubprogram(linkageName: "__await_suspend_wrapper__Z6f_coroi8MoveOnly11MoveAndCopy_init"
// CHECK: !{{[0-9]+}} = distinct !DISubprogram(linkageName: "_Z6f_coroi8MoveOnly11MoveAndCopy.__await_suspend_wrapper__init"
// CHECK-NEXT: !{{[0-9]+}} = !DIFile
// CHECK-NEXT: !{{[0-9]+}} = !DISubroutineType
// CHECK-NEXT: !{{[0-9]+}} = !DILocalVariable(arg: 1,
// CHECK-NEXT: !{{[0-9]+}} = !DILocation
// CHECK-NEXT: !{{[0-9]+}} = !DILocalVariable(arg: 2,

// CHECK: !{{[0-9]+}} = distinct !DISubprogram(linkageName: "__await_suspend_wrapper__Z6f_coroi8MoveOnly11MoveAndCopy_final"
// CHECK: !{{[0-9]+}} = distinct !DISubprogram(linkageName: "_Z6f_coroi8MoveOnly11MoveAndCopy.__await_suspend_wrapper__final"
// CHECK-NEXT: !{{[0-9]+}} = !DILocalVariable(arg: 1,
// CHECK-NEXT: !{{[0-9]+}} = !DILocation
// CHECK-NEXT: !{{[0-9]+}} = !DILocalVariable(arg: 2,
2 changes: 1 addition & 1 deletion clang/test/CodeGenCoroutines/pr65054.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,6 @@ MyTask FooBar() {
}

// CHECK-O0: define{{.*}}@_Z6FooBarv.resume
// CHECK-O0: call{{.*}}@__await_suspend_wrapper__Z6FooBarv_await(
// CHECK-O0: call{{.*}}@_Z6FooBarv.__await_suspend_wrapper__await(
// CHECK-O0-NOT: store
// CHECK-O0: ret void
Loading