49 changes: 25 additions & 24 deletions clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,17 +166,16 @@ static Value *joinDistinctValues(QualType Type, Value &Val1,
return JoinedVal;
}

// When widening does not change `Current`, return value will equal `&Prev`.
static Value &widenDistinctValues(QualType Type, Value &Prev,
const Environment &PrevEnv, Value &Current,
Environment &CurrentEnv,
Environment::ValueModel &Model) {
static WidenResult widenDistinctValues(QualType Type, Value &Prev,
const Environment &PrevEnv,
Value &Current, Environment &CurrentEnv,
Environment::ValueModel &Model) {
// Boolean-model widening.
if (auto *PrevBool = dyn_cast<BoolValue>(&Prev)) {
// If previous value was already Top, re-use that to (implicitly) indicate
// that no change occurred.
if (isa<TopBoolValue>(Prev))
return Prev;
// Safe to return `Prev` here, because Top is never dependent on the
// environment.
return {&Prev, LatticeEffect::Unchanged};

// We may need to widen to Top, but before we do so, check whether both
// values are implied to be either true or false in the current environment.
Expand All @@ -185,22 +184,24 @@ static Value &widenDistinctValues(QualType Type, Value &Prev,
bool TruePrev = PrevEnv.proves(PrevBool->formula());
bool TrueCur = CurrentEnv.proves(CurBool.formula());
if (TruePrev && TrueCur)
return CurrentEnv.getBoolLiteralValue(true);
return {&CurrentEnv.getBoolLiteralValue(true), LatticeEffect::Unchanged};
if (!TruePrev && !TrueCur &&
PrevEnv.proves(PrevEnv.arena().makeNot(PrevBool->formula())) &&
CurrentEnv.proves(CurrentEnv.arena().makeNot(CurBool.formula())))
return CurrentEnv.getBoolLiteralValue(false);
return {&CurrentEnv.getBoolLiteralValue(false), LatticeEffect::Unchanged};

return CurrentEnv.makeTopBoolValue();
return {&CurrentEnv.makeTopBoolValue(), LatticeEffect::Changed};
}

// FIXME: Add other built-in model widening.

// Custom-model widening.
if (auto *W = Model.widen(Type, Prev, PrevEnv, Current, CurrentEnv))
return *W;
if (auto Result = Model.widen(Type, Prev, PrevEnv, Current, CurrentEnv))
return *Result;

return equateUnknownValues(Prev.getKind()) ? Prev : Current;
return {&Current, equateUnknownValues(Prev.getKind())
? LatticeEffect::Unchanged
: LatticeEffect::Changed};
}

// Returns whether the values in `Map1` and `Map2` compare equal for those
Expand Down Expand Up @@ -271,7 +272,7 @@ llvm::MapVector<Key, Value *>
widenKeyToValueMap(const llvm::MapVector<Key, Value *> &CurMap,
const llvm::MapVector<Key, Value *> &PrevMap,
Environment &CurEnv, const Environment &PrevEnv,
Environment::ValueModel &Model, LatticeJoinEffect &Effect) {
Environment::ValueModel &Model, LatticeEffect &Effect) {
llvm::MapVector<Key, Value *> WidenedMap;
for (auto &Entry : CurMap) {
Key K = Entry.first;
Expand All @@ -290,11 +291,11 @@ widenKeyToValueMap(const llvm::MapVector<Key, Value *> &CurMap,
continue;
}

Value &WidenedVal = widenDistinctValues(K->getType(), *PrevIt->second,
PrevEnv, *Val, CurEnv, Model);
WidenedMap.insert({K, &WidenedVal});
if (&WidenedVal != PrevIt->second)
Effect = LatticeJoinEffect::Changed;
auto [WidenedVal, ValEffect] = widenDistinctValues(
K->getType(), *PrevIt->second, PrevEnv, *Val, CurEnv, Model);
WidenedMap.insert({K, WidenedVal});
if (ValEffect == LatticeEffect::Changed)
Effect = LatticeEffect::Changed;
}

return WidenedMap;
Expand Down Expand Up @@ -617,15 +618,15 @@ bool Environment::equivalentTo(const Environment &Other,
return true;
}

LatticeJoinEffect Environment::widen(const Environment &PrevEnv,
Environment::ValueModel &Model) {
LatticeEffect Environment::widen(const Environment &PrevEnv,
Environment::ValueModel &Model) {
assert(DACtx == PrevEnv.DACtx);
assert(ReturnVal == PrevEnv.ReturnVal);
assert(ReturnLoc == PrevEnv.ReturnLoc);
assert(ThisPointeeLoc == PrevEnv.ThisPointeeLoc);
assert(CallStack == PrevEnv.CallStack);

auto Effect = LatticeJoinEffect::Unchanged;
auto Effect = LatticeEffect::Unchanged;

// By the API, `PrevEnv` is a previous version of the environment for the same
// block, so we have some guarantees about its shape. In particular, it will
Expand All @@ -646,7 +647,7 @@ LatticeJoinEffect Environment::widen(const Environment &PrevEnv,
ExprToLoc.size() != PrevEnv.ExprToLoc.size() ||
ExprToVal.size() != PrevEnv.ExprToVal.size() ||
LocToVal.size() != PrevEnv.LocToVal.size())
Effect = LatticeJoinEffect::Changed;
Effect = LatticeEffect::Changed;

return Effect;
}
Expand Down
11 changes: 8 additions & 3 deletions clang/lib/Basic/Targets/M68k.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,16 +127,21 @@ bool M68kTargetInfo::hasFeature(StringRef Feature) const {

const char *const M68kTargetInfo::GCCRegNames[] = {
"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
"a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
"a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp",
"pc"};

ArrayRef<const char *> M68kTargetInfo::getGCCRegNames() const {
return llvm::ArrayRef(GCCRegNames);
}

const TargetInfo::GCCRegAlias M68kTargetInfo::GCCRegAliases[] = {
{{"bp"}, "a5"},
{{"fp"}, "a6"},
{{"usp", "ssp", "isp", "a7"}, "sp"},
};

ArrayRef<TargetInfo::GCCRegAlias> M68kTargetInfo::getGCCRegAliases() const {
// No aliases.
return std::nullopt;
return llvm::ArrayRef(GCCRegAliases);
}

bool M68kTargetInfo::validateAsmConstraint(
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Basic/Targets/M68k.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ namespace targets {

class LLVM_LIBRARY_VISIBILITY M68kTargetInfo : public TargetInfo {
static const char *const GCCRegNames[];
static const TargetInfo::GCCRegAlias GCCRegAliases[];

enum CPUKind {
CK_Unknown,
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/Basic/Targets/Mips.h
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo {
FPMode = isFP64Default() ? FP64 : FPXX;
NoOddSpreg = false;
bool OddSpregGiven = false;
bool StrictAlign = false;

for (const auto &Feature : Features) {
if (Feature == "+single-float")
Expand All @@ -330,6 +331,10 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo {
IsMicromips = true;
else if (Feature == "+mips32r6" || Feature == "+mips64r6")
HasUnalignedAccess = true;
// We cannot be sure that the order of strict-align vs mips32r6.
// Thus we need an extra variable here.
else if (Feature == "+strict-align")
StrictAlign = true;
else if (Feature == "+dsp")
DspRev = std::max(DspRev, DSP1);
else if (Feature == "+dspr2")
Expand Down Expand Up @@ -368,6 +373,9 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo {
if (FPMode == FPXX && !OddSpregGiven)
NoOddSpreg = true;

if (StrictAlign)
HasUnalignedAccess = false;

setDataLayout();

return true;
Expand Down
20 changes: 5 additions & 15 deletions clang/lib/CodeGen/BackendUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,18 +73,17 @@
#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
#include "llvm/Transforms/Instrumentation/InstrProfiling.h"
#include "llvm/Transforms/Instrumentation/KCFI.h"
#include "llvm/Transforms/Instrumentation/LowerAllowCheckPass.h"
#include "llvm/Transforms/Instrumentation/MemProfiler.h"
#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
#include "llvm/Transforms/Instrumentation/PGOInstrumentation.h"
#include "llvm/Transforms/Instrumentation/RemoveTrapsPass.h"
#include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h"
#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
#include "llvm/Transforms/ObjCARC.h"
#include "llvm/Transforms/Scalar/EarlyCSE.h"
#include "llvm/Transforms/Scalar/GVN.h"
#include "llvm/Transforms/Scalar/JumpThreading.h"
#include "llvm/Transforms/Scalar/SimplifyCFG.h"
#include "llvm/Transforms/Utils/Debugify.h"
#include "llvm/Transforms/Utils/EntryExitInstrumenter.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
Expand All @@ -100,21 +99,17 @@ using namespace llvm;
namespace llvm {
extern cl::opt<bool> PrintPipelinePasses;

cl::opt<bool> ClRemoveTraps("clang-remove-traps", cl::Optional,
cl::desc("Insert remove-traps pass."),
cl::init(false));

// Experiment to move sanitizers earlier.
static cl::opt<bool> ClSanitizeOnOptimizerEarlyEP(
"sanitizer-early-opt-ep", cl::Optional,
cl::desc("Insert sanitizers on OptimizerEarlyEP."), cl::init(false));
cl::desc("Insert sanitizers on OptimizerEarlyEP."));

extern cl::opt<InstrProfCorrelator::ProfCorrelatorKind> ProfileCorrelate;

// Re-link builtin bitcodes after optimization
cl::opt<bool> ClRelinkBuiltinBitcodePostop(
"relink-builtin-bitcode-postop", cl::Optional,
cl::desc("Re-link builtin bitcodes after optimization."), cl::init(false));
cl::desc("Re-link builtin bitcodes after optimization."));
} // namespace llvm

namespace {
Expand Down Expand Up @@ -751,18 +746,13 @@ static void addSanitizers(const Triple &TargetTriple,
PB.registerOptimizerLastEPCallback(SanitizersCallback);
}

if (ClRemoveTraps) {
if (LowerAllowCheckPass::IsRequested()) {
// We can optimize after inliner, and PGO profile matching. The hook below
// is called at the end `buildFunctionSimplificationPipeline`, which called
// from `buildInlinerPipeline`, which called after profile matching.
PB.registerScalarOptimizerLateEPCallback(
[](FunctionPassManager &FPM, OptimizationLevel Level) {
// RemoveTrapsPass expects trap blocks preceded by conditional
// branches, which usually is not the case without SimplifyCFG.
// TODO: Remove `SimplifyCFGPass` after switching to dedicated
// intrinsic.
FPM.addPass(SimplifyCFGPass());
FPM.addPass(RemoveTrapsPass());
FPM.addPass(LowerAllowCheckPass());
});
}
}
Expand Down
81 changes: 43 additions & 38 deletions clang/lib/CodeGen/CGAtomic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,11 +197,11 @@ namespace {
llvm::Value *getScalarRValValueOrNull(RValue RVal) const;

/// Converts an rvalue to integer value if needed.
llvm::Value *convertRValueToInt(RValue RVal, bool CastFP = true) const;
llvm::Value *convertRValueToInt(RValue RVal, bool CmpXchg = false) const;

RValue ConvertToValueOrAtomic(llvm::Value *IntVal, AggValueSlot ResultSlot,
SourceLocation Loc, bool AsValue,
bool CastFP = true) const;
bool CmpXchg = false) const;

/// Copy an atomic r-value into atomic-layout memory.
void emitCopyIntoMemory(RValue rvalue) const;
Expand Down Expand Up @@ -264,7 +264,7 @@ namespace {
llvm::AtomicOrdering AO, bool IsVolatile);
/// Emits atomic load as LLVM instruction.
llvm::Value *EmitAtomicLoadOp(llvm::AtomicOrdering AO, bool IsVolatile,
bool CastFP = true);
bool CmpXchg = false);
/// Emits atomic compare-and-exchange op as a libcall.
llvm::Value *EmitAtomicCompareExchangeLibcall(
llvm::Value *ExpectedAddr, llvm::Value *DesiredAddr,
Expand Down Expand Up @@ -1401,13 +1401,26 @@ RValue AtomicInfo::convertAtomicTempToRValue(Address addr,
LVal.getBaseInfo(), TBAAAccessInfo()));
}

/// Return true if \param ValTy is a type that should be casted to integer
/// around the atomic memory operation. If \param CmpXchg is true, then the
/// cast of a floating point type is made as that instruction can not have
/// floating point operands. TODO: Allow compare-and-exchange and FP - see
/// comment in AtomicExpandPass.cpp.
static bool shouldCastToInt(llvm::Type *ValTy, bool CmpXchg) {
if (ValTy->isFloatingPointTy())
return ValTy->isX86_FP80Ty() || CmpXchg;
return !ValTy->isIntegerTy() && !ValTy->isPointerTy();
}

RValue AtomicInfo::ConvertToValueOrAtomic(llvm::Value *Val,
AggValueSlot ResultSlot,
SourceLocation Loc, bool AsValue,
bool CastFP) const {
bool CmpXchg) const {
// Try not to in some easy cases.
assert((Val->getType()->isIntegerTy() || Val->getType()->isIEEELikeFPTy()) &&
"Expected integer or floating point value");
assert((Val->getType()->isIntegerTy() || Val->getType()->isPointerTy() ||
Val->getType()->isIEEELikeFPTy()) &&
"Expected integer, pointer or floating point value when converting "
"result.");
if (getEvaluationKind() == TEK_Scalar &&
(((!LVal.isBitField() ||
LVal.getBitFieldInfo().Size == ValueSizeInBits) &&
Expand All @@ -1416,13 +1429,12 @@ RValue AtomicInfo::ConvertToValueOrAtomic(llvm::Value *Val,
auto *ValTy = AsValue
? CGF.ConvertTypeForMem(ValueTy)
: getAtomicAddress().getElementType();
if (ValTy->isIntegerTy() || (!CastFP && ValTy->isIEEELikeFPTy())) {
if (!shouldCastToInt(ValTy, CmpXchg)) {
assert((!ValTy->isIntegerTy() || Val->getType() == ValTy) &&
"Different integer types.");
return RValue::get(CGF.EmitFromMemory(Val, ValueTy));
} else if (ValTy->isPointerTy())
return RValue::get(CGF.Builder.CreateIntToPtr(Val, ValTy));
else if (llvm::CastInst::isBitCastable(Val->getType(), ValTy))
}
if (llvm::CastInst::isBitCastable(Val->getType(), ValTy))
return RValue::get(CGF.Builder.CreateBitCast(Val, ValTy));
}

Expand Down Expand Up @@ -1459,10 +1471,10 @@ void AtomicInfo::EmitAtomicLoadLibcall(llvm::Value *AddForLoaded,
}

llvm::Value *AtomicInfo::EmitAtomicLoadOp(llvm::AtomicOrdering AO,
bool IsVolatile, bool CastFP) {
bool IsVolatile, bool CmpXchg) {
// Okay, we're doing this natively.
Address Addr = getAtomicAddress();
if (!(Addr.getElementType()->isIEEELikeFPTy() && !CastFP))
if (shouldCastToInt(Addr.getElementType(), CmpXchg))
Addr = castToAtomicIntPointer(Addr);
llvm::LoadInst *Load = CGF.Builder.CreateLoad(Addr, "atomic-load");
Load->setAtomic(AO);
Expand Down Expand Up @@ -1523,16 +1535,15 @@ RValue AtomicInfo::EmitAtomicLoad(AggValueSlot ResultSlot, SourceLocation Loc,
}

// Okay, we're doing this natively.
auto *Load = EmitAtomicLoadOp(AO, IsVolatile, /*CastFP=*/false);
auto *Load = EmitAtomicLoadOp(AO, IsVolatile);

// If we're ignoring an aggregate return, don't do anything.
if (getEvaluationKind() == TEK_Aggregate && ResultSlot.isIgnored())
return RValue::getAggregate(Address::invalid(), false);

// Okay, turn that back into the original value or atomic (for non-simple
// lvalues) type.
return ConvertToValueOrAtomic(Load, ResultSlot, Loc, AsValue,
/*CastFP=*/false);
return ConvertToValueOrAtomic(Load, ResultSlot, Loc, AsValue);
}

/// Emit a load from an l-value of atomic type. Note that the r-value
Expand Down Expand Up @@ -1601,20 +1612,17 @@ llvm::Value *AtomicInfo::getScalarRValValueOrNull(RValue RVal) const {
return nullptr;
}

llvm::Value *AtomicInfo::convertRValueToInt(RValue RVal, bool CastFP) const {
llvm::Value *AtomicInfo::convertRValueToInt(RValue RVal, bool CmpXchg) const {
// If we've got a scalar value of the right size, try to avoid going
// through memory. Floats get casted if needed by AtomicExpandPass.
if (llvm::Value *Value = getScalarRValValueOrNull(RVal)) {
if (isa<llvm::IntegerType>(Value->getType()) ||
(!CastFP && Value->getType()->isIEEELikeFPTy()))
if (!shouldCastToInt(Value->getType(), CmpXchg))
return CGF.EmitToMemory(Value, ValueTy);
else {
llvm::IntegerType *InputIntTy = llvm::IntegerType::get(
CGF.getLLVMContext(),
LVal.isSimple() ? getValueSizeInBits() : getAtomicSizeInBits());
if (isa<llvm::PointerType>(Value->getType()))
return CGF.Builder.CreatePtrToInt(Value, InputIntTy);
else if (llvm::BitCastInst::isBitCastable(Value->getType(), InputIntTy))
if (llvm::BitCastInst::isBitCastable(Value->getType(), InputIntTy))
return CGF.Builder.CreateBitCast(Value, InputIntTy);
}
}
Expand Down Expand Up @@ -1687,13 +1695,14 @@ std::pair<RValue, llvm::Value *> AtomicInfo::EmitAtomicCompareExchange(

// If we've got a scalar value of the right size, try to avoid going
// through memory.
auto *ExpectedVal = convertRValueToInt(Expected);
auto *DesiredVal = convertRValueToInt(Desired);
auto *ExpectedVal = convertRValueToInt(Expected, /*CmpXchg=*/true);
auto *DesiredVal = convertRValueToInt(Desired, /*CmpXchg=*/true);
auto Res = EmitAtomicCompareExchangeOp(ExpectedVal, DesiredVal, Success,
Failure, IsWeak);
return std::make_pair(
ConvertToValueOrAtomic(Res.first, AggValueSlot::ignored(),
SourceLocation(), /*AsValue=*/false),
SourceLocation(), /*AsValue=*/false,
/*CmpXchg=*/true),
Res.second);
}

Expand Down Expand Up @@ -1787,7 +1796,7 @@ void AtomicInfo::EmitAtomicUpdateOp(
auto Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO);

// Do the atomic load.
auto *OldVal = EmitAtomicLoadOp(Failure, IsVolatile);
auto *OldVal = EmitAtomicLoadOp(Failure, IsVolatile, /*CmpXchg=*/true);
// For non-simple lvalues perform compare-and-swap procedure.
auto *ContBB = CGF.createBasicBlock("atomic_cont");
auto *ExitBB = CGF.createBasicBlock("atomic_exit");
Expand All @@ -1803,7 +1812,8 @@ void AtomicInfo::EmitAtomicUpdateOp(
CGF.Builder.CreateStore(PHI, NewAtomicIntAddr);
}
auto OldRVal = ConvertToValueOrAtomic(PHI, AggValueSlot::ignored(),
SourceLocation(), /*AsValue=*/false);
SourceLocation(), /*AsValue=*/false,
/*CmpXchg=*/true);
EmitAtomicUpdateValue(CGF, *this, OldRVal, UpdateOp, NewAtomicAddr);
auto *DesiredVal = CGF.Builder.CreateLoad(NewAtomicIntAddr);
// Try to write new value using cmpxchg operation.
Expand Down Expand Up @@ -1869,7 +1879,7 @@ void AtomicInfo::EmitAtomicUpdateOp(llvm::AtomicOrdering AO, RValue UpdateRVal,
auto Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO);

// Do the atomic load.
auto *OldVal = EmitAtomicLoadOp(Failure, IsVolatile);
auto *OldVal = EmitAtomicLoadOp(Failure, IsVolatile, /*CmpXchg=*/true);
// For non-simple lvalues perform compare-and-swap procedure.
auto *ContBB = CGF.createBasicBlock("atomic_cont");
auto *ExitBB = CGF.createBasicBlock("atomic_exit");
Expand Down Expand Up @@ -1969,21 +1979,16 @@ void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest,
}

// Okay, we're doing this natively.
llvm::Value *ValToStore =
atomics.convertRValueToInt(rvalue, /*CastFP=*/false);
llvm::Value *ValToStore = atomics.convertRValueToInt(rvalue);

// Do the atomic store.
Address Addr = atomics.getAtomicAddress();
bool ShouldCastToInt = true;
if (llvm::Value *Value = atomics.getScalarRValValueOrNull(rvalue))
if (isa<llvm::IntegerType>(Value->getType()) ||
Value->getType()->isIEEELikeFPTy())
ShouldCastToInt = false;
if (ShouldCastToInt) {
Addr = atomics.castToAtomicIntPointer(Addr);
ValToStore = Builder.CreateIntCast(ValToStore, Addr.getElementType(),
/*isSigned=*/false);
}
if (shouldCastToInt(Value->getType(), /*CmpXchg=*/false)) {
Addr = atomics.castToAtomicIntPointer(Addr);
ValToStore = Builder.CreateIntCast(ValToStore, Addr.getElementType(),
/*isSigned=*/false);
}
llvm::StoreInst *store = Builder.CreateStore(ValToStore, Addr);

if (AO == llvm::AtomicOrdering::Acquire)
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGBlocks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -962,7 +962,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
}

// If it's a reference variable, copy the reference into the block field.
} else if (auto refType = type->getAs<ReferenceType>()) {
} else if (type->getAs<ReferenceType>()) {
Builder.CreateStore(src.emitRawPointer(*this), blockField);

// If type is const-qualified, copy the value into the block field.
Expand Down
20 changes: 9 additions & 11 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "ABIInfo.h"
#include "CGCUDARuntime.h"
#include "CGCXXABI.h"
#include "CGHLSLRuntime.h"
#include "CGObjCRuntime.h"
#include "CGOpenCLRuntime.h"
#include "CGRecordLayout.h"
Expand Down Expand Up @@ -5835,7 +5836,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
EmitLifetimeEnd(TmpSize, TmpPtr);
return Call;
}
[[fallthrough]];
llvm_unreachable("Unexpected enqueue_kernel signature");
}
// OpenCL v2.0 s6.13.17.6 - Kernel query functions need bitcast of block
// parameter.
Expand Down Expand Up @@ -7281,8 +7282,6 @@ static const std::pair<unsigned, unsigned> NEONEquivalentIntrinsicMap[] = {
{ NEON::BI__builtin_neon_vabdq_f16, NEON::BI__builtin_neon_vabdq_v, },
{ NEON::BI__builtin_neon_vabs_f16, NEON::BI__builtin_neon_vabs_v, },
{ NEON::BI__builtin_neon_vabsq_f16, NEON::BI__builtin_neon_vabsq_v, },
{ NEON::BI__builtin_neon_vbsl_f16, NEON::BI__builtin_neon_vbsl_v, },
{ NEON::BI__builtin_neon_vbslq_f16, NEON::BI__builtin_neon_vbslq_v, },
{ NEON::BI__builtin_neon_vcage_f16, NEON::BI__builtin_neon_vcage_v, },
{ NEON::BI__builtin_neon_vcageq_f16, NEON::BI__builtin_neon_vcageq_v, },
{ NEON::BI__builtin_neon_vcagt_f16, NEON::BI__builtin_neon_vcagt_v, },
Expand All @@ -7301,8 +7300,6 @@ static const std::pair<unsigned, unsigned> NEONEquivalentIntrinsicMap[] = {
{ NEON::BI__builtin_neon_vclezq_f16, NEON::BI__builtin_neon_vclezq_v, },
{ NEON::BI__builtin_neon_vcltz_f16, NEON::BI__builtin_neon_vcltz_v, },
{ NEON::BI__builtin_neon_vcltzq_f16, NEON::BI__builtin_neon_vcltzq_v, },
{ NEON::BI__builtin_neon_vext_f16, NEON::BI__builtin_neon_vext_v, },
{ NEON::BI__builtin_neon_vextq_f16, NEON::BI__builtin_neon_vextq_v, },
{ NEON::BI__builtin_neon_vfma_f16, NEON::BI__builtin_neon_vfma_v, },
{ NEON::BI__builtin_neon_vfma_lane_f16, NEON::BI__builtin_neon_vfma_lane_v, },
{ NEON::BI__builtin_neon_vfma_laneq_f16, NEON::BI__builtin_neon_vfma_laneq_v, },
Expand Down Expand Up @@ -7405,12 +7402,6 @@ static const std::pair<unsigned, unsigned> NEONEquivalentIntrinsicMap[] = {
{ NEON::BI__builtin_neon_vst4_lane_bf16, NEON::BI__builtin_neon_vst4_lane_v },
{ NEON::BI__builtin_neon_vst4q_bf16, NEON::BI__builtin_neon_vst4q_v },
{ NEON::BI__builtin_neon_vst4q_lane_bf16, NEON::BI__builtin_neon_vst4q_lane_v },
{ NEON::BI__builtin_neon_vtrn_f16, NEON::BI__builtin_neon_vtrn_v, },
{ NEON::BI__builtin_neon_vtrnq_f16, NEON::BI__builtin_neon_vtrnq_v, },
{ NEON::BI__builtin_neon_vuzp_f16, NEON::BI__builtin_neon_vuzp_v, },
{ NEON::BI__builtin_neon_vuzpq_f16, NEON::BI__builtin_neon_vuzpq_v, },
{ NEON::BI__builtin_neon_vzip_f16, NEON::BI__builtin_neon_vzip_v, },
{ NEON::BI__builtin_neon_vzipq_f16, NEON::BI__builtin_neon_vzipq_v, },
// The mangling rules cause us to have one ID for each type for vldap1(q)_lane
// and vstl1(q)_lane, but codegen is equivalent for all of them. Choose an
// arbitrary one to be handled as tha canonical variation.
Expand Down Expand Up @@ -18182,6 +18173,13 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
return nullptr;

switch (BuiltinID) {
case Builtin::BI__builtin_hlsl_elementwise_all: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
return Builder.CreateIntrinsic(
/*ReturnType=*/llvm::Type::getInt1Ty(getLLVMContext()),
CGM.getHLSLRuntime().getAllIntrinsic(), ArrayRef<Value *>{Op0}, nullptr,
"hlsl.all");
}
case Builtin::BI__builtin_hlsl_elementwise_any: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
return Builder.CreateIntrinsic(
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4379,7 +4379,8 @@ void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType,
NNAttr = getNonNullAttr(AC.getDecl(), PVD, ArgType, ArgNo);

bool CanCheckNullability = false;
if (SanOpts.has(SanitizerKind::NullabilityArg) && !NNAttr && PVD) {
if (SanOpts.has(SanitizerKind::NullabilityArg) && !NNAttr && PVD &&
!PVD->getType()->isRecordType()) {
auto Nullability = PVD->getType()->getNullability();
CanCheckNullability = Nullability &&
*Nullability == NullabilityKind::NonNull &&
Expand Down
3 changes: 1 addition & 2 deletions clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ using namespace CodeGen;
// Experiment to make sanitizers easier to debug
static llvm::cl::opt<bool> ClSanitizeDebugDeoptimization(
"ubsan-unique-traps", llvm::cl::Optional,
llvm::cl::desc("Deoptimize traps for UBSAN so there is 1 trap per check"),
llvm::cl::init(false));
llvm::cl::desc("Deoptimize traps for UBSAN so there is 1 trap per check"));

//===--------------------------------------------------------------------===//
// Miscellaneous Helper Methods
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/CodeGen/CGExprComplex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -319,12 +319,12 @@ class ComplexExprEmitter
// doubles the exponent of SmallerType.LargestFiniteVal)
if (llvm::APFloat::semanticsMaxExponent(ElementTypeSemantics) * 2 + 1 <=
llvm::APFloat::semanticsMaxExponent(HigherElementTypeSemantics)) {
FPHasBeenPromoted = true;
return CGF.getContext().getComplexType(HigherElementType);
} else {
FPHasBeenPromoted = true;
DiagnosticsEngine &Diags = CGF.CGM.getDiags();
Diags.Report(diag::warn_next_larger_fp_type_same_size_than_fp);
return CGF.getContext().getComplexType(ElementType);
return QualType();
}
}

Expand Down Expand Up @@ -1037,7 +1037,7 @@ ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) {
LHSi = llvm::Constant::getNullValue(RHSi->getType());
if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Improved ||
(Op.FPFeatures.getComplexRange() == LangOptions::CX_Promoted &&
FPHasBeenPromoted))
!FPHasBeenPromoted))
return EmitRangeReductionDiv(LHSr, LHSi, RHSr, RHSi);
else if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Basic ||
Op.FPFeatures.getComplexRange() == LangOptions::CX_Promoted)
Expand Down
20 changes: 6 additions & 14 deletions clang/lib/CodeGen/CGHLSLRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
#include "CodeGenModule.h"
#include "clang/AST/Decl.h"
#include "clang/Basic/TargetOptions.h"
#include "llvm/IR/IntrinsicsDirectX.h"
#include "llvm/IR/IntrinsicsSPIRV.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/FormatVariadic.h"
Expand Down Expand Up @@ -117,6 +115,10 @@ GlobalVariable *replaceBuffer(CGHLSLRuntime::Buffer &Buf) {

} // namespace

llvm::Triple::ArchType CGHLSLRuntime::getArch() {
return CGM.getTarget().getTriple().getArch();
}

void CGHLSLRuntime::addConstant(VarDecl *D, Buffer &CB) {
if (D->getStorageClass() == SC_Static) {
// For static inside cbuffer, take as global static.
Expand Down Expand Up @@ -343,18 +345,8 @@ llvm::Value *CGHLSLRuntime::emitInputSemantic(IRBuilder<> &B,
return B.CreateCall(FunctionCallee(DxGroupIndex));
}
if (D.hasAttr<HLSLSV_DispatchThreadIDAttr>()) {
llvm::Function *ThreadIDIntrinsic;
switch (CGM.getTarget().getTriple().getArch()) {
case llvm::Triple::dxil:
ThreadIDIntrinsic = CGM.getIntrinsic(Intrinsic::dx_thread_id);
break;
case llvm::Triple::spirv:
ThreadIDIntrinsic = CGM.getIntrinsic(Intrinsic::spv_thread_id);
break;
default:
llvm_unreachable("Input semantic not supported by target");
break;
}
llvm::Function *ThreadIDIntrinsic =
CGM.getIntrinsic(getThreadIdIntrinsic());
return buildVectorInput(B, ThreadIDIntrinsic, Ty);
}
assert(false && "Unhandled parameter attribute");
Expand Down
32 changes: 32 additions & 0 deletions clang/lib/CodeGen/CGHLSLRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@
#define LLVM_CLANG_LIB_CODEGEN_CGHLSLRUNTIME_H

#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IntrinsicsDirectX.h"
#include "llvm/IR/IntrinsicsSPIRV.h"

#include "clang/Basic/Builtins.h"
#include "clang/Basic/HLSLRuntime.h"

#include "llvm/ADT/SmallVector.h"
Expand All @@ -26,6 +30,22 @@
#include <optional>
#include <vector>

// A function generator macro for picking the right intrinsic
// for the target backend
#define GENERATE_HLSL_INTRINSIC_FUNCTION(FunctionName, IntrinsicPostfix) \
llvm::Intrinsic::ID get##FunctionName##Intrinsic() { \
llvm::Triple::ArchType Arch = getArch(); \
switch (Arch) { \
case llvm::Triple::dxil: \
return llvm::Intrinsic::dx_##IntrinsicPostfix; \
case llvm::Triple::spirv: \
return llvm::Intrinsic::spv_##IntrinsicPostfix; \
default: \
llvm_unreachable("Intrinsic " #IntrinsicPostfix \
" not supported by target architecture"); \
} \
}

namespace llvm {
class GlobalVariable;
class Function;
Expand All @@ -48,6 +68,17 @@ class CodeGenModule;

class CGHLSLRuntime {
public:
//===----------------------------------------------------------------------===//
// Start of reserved area for HLSL intrinsic getters.
//===----------------------------------------------------------------------===//

GENERATE_HLSL_INTRINSIC_FUNCTION(All, all)
GENERATE_HLSL_INTRINSIC_FUNCTION(ThreadId, thread_id)

//===----------------------------------------------------------------------===//
// End of reserved area for HLSL intrinsic getters.
//===----------------------------------------------------------------------===//

struct BufferResBinding {
// The ID like 2 in register(b2, space1).
std::optional<unsigned> Reg;
Expand Down Expand Up @@ -96,6 +127,7 @@ class CGHLSLRuntime {
BufferResBinding &Binding);
void addConstant(VarDecl *D, Buffer &CB);
void addBufferDecls(const DeclContext *DC, Buffer &CB);
llvm::Triple::ArchType getArch();
llvm::SmallVector<Buffer> Buffers;
};

Expand Down
6 changes: 3 additions & 3 deletions clang/lib/CodeGen/CGOpenMPRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2648,9 +2648,9 @@ void CGOpenMPRuntime::emitDistributeStaticInit(
void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
SourceLocation Loc,
OpenMPDirectiveKind DKind) {
assert(DKind == OMPD_distribute || DKind == OMPD_for ||
DKind == OMPD_sections &&
"Expected distribute, for, or sections directive kind");
assert((DKind == OMPD_distribute || DKind == OMPD_for ||
DKind == OMPD_sections) &&
"Expected distribute, for, or sections directive kind");
if (!CGF.HaveInsertPoint())
return;
// Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
Expand Down
57 changes: 40 additions & 17 deletions clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,18 +185,21 @@ struct CGRecordLowering {
/// Lowers an ASTRecordLayout to a llvm type.
void lower(bool NonVirtualBaseType);
void lowerUnion(bool isNoUniqueAddress);
void accumulateFields();
void accumulateFields(bool isNonVirtualBaseType);
RecordDecl::field_iterator
accumulateBitFields(RecordDecl::field_iterator Field,
accumulateBitFields(bool isNonVirtualBaseType,
RecordDecl::field_iterator Field,
RecordDecl::field_iterator FieldEnd);
void computeVolatileBitfields();
void accumulateBases();
void accumulateVPtrs();
void accumulateVBases();
/// Recursively searches all of the bases to find out if a vbase is
/// not the primary vbase of some base class.
bool hasOwnStorage(const CXXRecordDecl *Decl, const CXXRecordDecl *Query);
bool hasOwnStorage(const CXXRecordDecl *Decl,
const CXXRecordDecl *Query) const;
void calculateZeroInit();
CharUnits calculateTailClippingOffset(bool isNonVirtualBaseType) const;
/// Lowers bitfield storage types to I8 arrays for bitfields with tail
/// padding that is or can potentially be used.
void clipTailPadding();
Expand Down Expand Up @@ -287,7 +290,7 @@ void CGRecordLowering::lower(bool NVBaseType) {
computeVolatileBitfields();
return;
}
accumulateFields();
accumulateFields(NVBaseType);
// RD implies C++.
if (RD) {
accumulateVPtrs();
Expand Down Expand Up @@ -378,12 +381,12 @@ void CGRecordLowering::lowerUnion(bool isNoUniqueAddress) {
Packed = true;
}

void CGRecordLowering::accumulateFields() {
void CGRecordLowering::accumulateFields(bool isNonVirtualBaseType) {
for (RecordDecl::field_iterator Field = D->field_begin(),
FieldEnd = D->field_end();
Field != FieldEnd;) {
if (Field->isBitField()) {
Field = accumulateBitFields(Field, FieldEnd);
Field = accumulateBitFields(isNonVirtualBaseType, Field, FieldEnd);
assert((Field == FieldEnd || !Field->isBitField()) &&
"Failed to accumulate all the bitfields");
} else if (Field->isZeroSize(Context)) {
Expand All @@ -404,9 +407,12 @@ void CGRecordLowering::accumulateFields() {
}

// Create members for bitfields. Field is a bitfield, and FieldEnd is the end
// iterator of the record. Return the first non-bitfield encountered.
// iterator of the record. Return the first non-bitfield encountered. We need
// to know whether this is the base or complete layout, as virtual bases could
// affect the upper bound of bitfield access unit allocation.
RecordDecl::field_iterator
CGRecordLowering::accumulateBitFields(RecordDecl::field_iterator Field,
CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType,
RecordDecl::field_iterator Field,
RecordDecl::field_iterator FieldEnd) {
if (isDiscreteBitFieldABI()) {
// Run stores the first element of the current run of bitfields. FieldEnd is
Expand Down Expand Up @@ -505,6 +511,10 @@ CGRecordLowering::accumulateBitFields(RecordDecl::field_iterator Field,
bitsToCharUnits(Context.getTargetInfo().getRegisterWidth());
unsigned CharBits = Context.getCharWidth();

// Limit of useable tail padding at end of the record. Computed lazily and
// cached here.
CharUnits ScissorOffset = CharUnits::Zero();

// Data about the start of the span we're accumulating to create an access
// unit from. Begin is the first bitfield of the span. If Begin is FieldEnd,
// we've not got a current span. The span starts at the BeginOffset character
Expand Down Expand Up @@ -630,10 +640,14 @@ CGRecordLowering::accumulateBitFields(RecordDecl::field_iterator Field,
LimitOffset = bitsToCharUnits(getFieldBitOffset(*Probe));
goto FoundLimit;
}
// We reached the end of the fields. We can't necessarily use tail
// padding in C++ structs, so the NonVirtual size is what we must
// use there.
LimitOffset = RD ? Layout.getNonVirtualSize() : Layout.getDataSize();
// We reached the end of the fields, determine the bounds of useable
// tail padding. As this can be complex for C++, we cache the result.
if (ScissorOffset.isZero()) {
ScissorOffset = calculateTailClippingOffset(isNonVirtualBaseType);
assert(!ScissorOffset.isZero() && "Tail clipping at zero");
}

LimitOffset = ScissorOffset;
FoundLimit:;

CharUnits TypeSize = getSize(Type);
Expand Down Expand Up @@ -838,13 +852,17 @@ void CGRecordLowering::accumulateVPtrs() {
llvm::PointerType::getUnqual(Types.getLLVMContext())));
}

void CGRecordLowering::accumulateVBases() {
CharUnits
CGRecordLowering::calculateTailClippingOffset(bool isNonVirtualBaseType) const {
if (!RD)
return Layout.getDataSize();

CharUnits ScissorOffset = Layout.getNonVirtualSize();
// In the itanium ABI, it's possible to place a vbase at a dsize that is
// smaller than the nvsize. Here we check to see if such a base is placed
// before the nvsize and set the scissor offset to that, instead of the
// nvsize.
if (isOverlappingVBaseABI())
if (!isNonVirtualBaseType && isOverlappingVBaseABI())
for (const auto &Base : RD->vbases()) {
const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
if (BaseDecl->isEmpty())
Expand All @@ -856,8 +874,13 @@ void CGRecordLowering::accumulateVBases() {
ScissorOffset = std::min(ScissorOffset,
Layout.getVBaseClassOffset(BaseDecl));
}
Members.push_back(MemberInfo(ScissorOffset, MemberInfo::Scissor, nullptr,
RD));

return ScissorOffset;
}

void CGRecordLowering::accumulateVBases() {
Members.push_back(MemberInfo(calculateTailClippingOffset(false),
MemberInfo::Scissor, nullptr, RD));
for (const auto &Base : RD->vbases()) {
const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
if (BaseDecl->isEmpty())
Expand All @@ -882,7 +905,7 @@ void CGRecordLowering::accumulateVBases() {
}

bool CGRecordLowering::hasOwnStorage(const CXXRecordDecl *Decl,
const CXXRecordDecl *Query) {
const CXXRecordDecl *Query) const {
const ASTRecordLayout &DeclLayout = Context.getASTRecordLayout(Decl);
if (DeclLayout.isPrimaryBaseVirtual() && DeclLayout.getPrimaryBase() == Query)
return false;
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/CodeGen/CodeGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -990,7 +990,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
// return value. Initialize the flag to 'true' and refine it in EmitParmDecl.
if (SanOpts.has(SanitizerKind::NullabilityReturn)) {
auto Nullability = FnRetTy->getNullability();
if (Nullability && *Nullability == NullabilityKind::NonNull) {
if (Nullability && *Nullability == NullabilityKind::NonNull &&
!FnRetTy->isRecordType()) {
if (!(SanOpts.has(SanitizerKind::ReturnsNonnullAttribute) &&
CurCodeDecl && CurCodeDecl->getAttr<ReturnsNonNullAttr>()))
RetValNullabilityPrecondition =
Expand Down
9 changes: 8 additions & 1 deletion clang/lib/CodeGen/CodeGenTBAA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "clang/AST/Mangle.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/LLVMContext.h"
Expand Down Expand Up @@ -319,7 +320,13 @@ CodeGenTBAA::CollectFields(uint64_t BaseOffset,
// base type.
if ((*i)->isBitField()) {
const CGBitFieldInfo &Info = CGRL.getBitFieldInfo(*i);
if (Info.Offset != 0)
// For big endian targets the first bitfield in the consecutive run is
// at the most-significant end; see CGRecordLowering::setBitFieldInfo
// for more information.
bool IsBE = Context.getTargetInfo().isBigEndian();
bool IsFirst = IsBE ? Info.StorageSize - (Info.Offset + Info.Size) == 0
: Info.Offset == 0;
if (!IsFirst)
continue;
unsigned CurrentBitFieldSize = Info.StorageSize;
uint64_t Size =
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/CodeGen/Targets/X86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1069,6 +1069,12 @@ Address X86_32ABIInfo::EmitVAArg(CodeGenFunction &CGF,

auto TypeInfo = getContext().getTypeInfoInChars(Ty);

CCState State(*const_cast<CGFunctionInfo *>(CGF.CurFnInfo));
ABIArgInfo AI = classifyArgumentType(Ty, State, /*ArgIndex*/ 0);
// Empty records are ignored for parameter passing purposes.
if (AI.isIgnore())
return CGF.CreateMemTemp(Ty);

// x86-32 changes the alignment of certain arguments on the stack.
//
// Just messing with TypeInfo like this works because we never pass
Expand Down
21 changes: 9 additions & 12 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#include "ToolChains/WebAssembly.h"
#include "ToolChains/XCore.h"
#include "ToolChains/ZOS.h"
#include "clang/Basic/DiagnosticDriver.h"
#include "clang/Basic/TargetID.h"
#include "clang/Basic/Version.h"
#include "clang/Config/config.h"
Expand Down Expand Up @@ -5814,19 +5815,9 @@ static const char *GetModuleOutputPath(Compilation &C, const JobAction &JA,
(C.getArgs().hasArg(options::OPT_fmodule_output) ||
C.getArgs().hasArg(options::OPT_fmodule_output_EQ)));

if (Arg *ModuleOutputEQ =
C.getArgs().getLastArg(options::OPT_fmodule_output_EQ))
return C.addResultFile(ModuleOutputEQ->getValue(), &JA);
SmallString<256> OutputPath =
tools::getCXX20NamedModuleOutputPath(C.getArgs(), BaseInput);

SmallString<64> OutputPath;
Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o);
if (FinalOutput && C.getArgs().hasArg(options::OPT_c))
OutputPath = FinalOutput->getValue();
else
OutputPath = BaseInput;

const char *Extension = types::getTypeTempSuffix(JA.getType());
llvm::sys::path::replace_extension(OutputPath, Extension);
return C.addResultFile(C.getArgs().MakeArgString(OutputPath.c_str()), &JA);
}

Expand Down Expand Up @@ -5899,6 +5890,12 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
&JA);
}

if (JA.getType() == types::TY_API_INFO &&
C.getArgs().hasArg(options::OPT_emit_extension_symbol_graphs) &&
C.getArgs().hasArg(options::OPT_o))
Diag(clang::diag::err_drv_unexpected_symbol_graph_output)
<< C.getArgs().getLastArgValue(options::OPT_o);

// DXC defaults to standard out when generating assembly. We check this after
// any DXC flags that might specify a file.
if (AtTopLevel && JA.getType() == types::TY_PP_Asm && IsDXCMode())
Expand Down
51 changes: 47 additions & 4 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3839,6 +3839,24 @@ bool Driver::getDefaultModuleCachePath(SmallVectorImpl<char> &Result) {
return false;
}

llvm::SmallString<256>
clang::driver::tools::getCXX20NamedModuleOutputPath(const ArgList &Args,
const char *BaseInput) {
if (Arg *ModuleOutputEQ = Args.getLastArg(options::OPT_fmodule_output_EQ))
return StringRef(ModuleOutputEQ->getValue());

SmallString<256> OutputPath;
if (Arg *FinalOutput = Args.getLastArg(options::OPT_o);
FinalOutput && Args.hasArg(options::OPT_c))
OutputPath = FinalOutput->getValue();
else
OutputPath = BaseInput;

const char *Extension = types::getTypeTempSuffix(types::TY_ModuleFile);
llvm::sys::path::replace_extension(OutputPath, Extension);
return OutputPath;
}

static bool RenderModulesOptions(Compilation &C, const Driver &D,
const ArgList &Args, const InputInfo &Input,
const InputInfo &Output, bool HaveStd20,
Expand Down Expand Up @@ -4027,9 +4045,18 @@ static bool RenderModulesOptions(Compilation &C, const Driver &D,
// module fragment.
CmdArgs.push_back("-fskip-odr-check-in-gmf");

// Claim `-fmodule-output` and `-fmodule-output=` to avoid unused warnings.
Args.ClaimAllArgs(options::OPT_fmodule_output);
Args.ClaimAllArgs(options::OPT_fmodule_output_EQ);
// We need to include the case the input file is a module file here.
// Since the default compilation model for C++ module interface unit will
// create temporary module file and compile the temporary module file
// to get the object file. Then the `-fmodule-output` flag will be
// brought to the second compilation process. So we have to claim it for
// the case too.
if (Input.getType() == driver::types::TY_CXXModule ||
Input.getType() == driver::types::TY_PP_CXXModule ||
Input.getType() == driver::types::TY_ModuleFile) {
Args.ClaimAllArgs(options::OPT_fmodule_output);
Args.ClaimAllArgs(options::OPT_fmodule_output_EQ);
}

return HaveModules;
}
Expand Down Expand Up @@ -5019,11 +5046,26 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
assert(JA.getType() == types::TY_API_INFO &&
"Extract API actions must generate a API information.");
CmdArgs.push_back("-extract-api");

if (Arg *PrettySGFArg = Args.getLastArg(options::OPT_emit_pretty_sgf))
PrettySGFArg->render(Args, CmdArgs);

Arg *SymbolGraphDirArg = Args.getLastArg(options::OPT_symbol_graph_dir_EQ);

if (Arg *ProductNameArg = Args.getLastArg(options::OPT_product_name_EQ))
ProductNameArg->render(Args, CmdArgs);
if (Arg *ExtractAPIIgnoresFileArg =
Args.getLastArg(options::OPT_extract_api_ignores_EQ))
ExtractAPIIgnoresFileArg->render(Args, CmdArgs);
if (Arg *EmitExtensionSymbolGraphs =
Args.getLastArg(options::OPT_emit_extension_symbol_graphs)) {
if (!SymbolGraphDirArg)
D.Diag(diag::err_drv_missing_symbol_graph_dir);

EmitExtensionSymbolGraphs->render(Args, CmdArgs);
}
if (SymbolGraphDirArg)
SymbolGraphDirArg->render(Args, CmdArgs);
} else {
assert((isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) &&
"Invalid action for clang tool.");
Expand Down Expand Up @@ -5840,7 +5882,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CM = "large";
if (Triple.isAArch64(64)) {
Ok = CM == "tiny" || CM == "small" || CM == "large";
if (CM == "large" && RelocationModel != llvm::Reloc::Static)
if (CM == "large" && !Triple.isOSBinFormatMachO() &&
RelocationModel != llvm::Reloc::Static)
D.Diag(diag::err_drv_argument_only_allowed_with)
<< A->getAsString(Args) << "-fno-pic";
} else if (Triple.isLoongArch()) {
Expand Down
15 changes: 15 additions & 0 deletions clang/lib/Driver/ToolChains/Clang.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,21 @@ DwarfFissionKind getDebugFissionKind(const Driver &D,
const llvm::opt::ArgList &Args,
llvm::opt::Arg *&Arg);

// Calculate the output path of the module file when compiling a module unit
// with the `-fmodule-output` option or `-fmodule-output=` option specified.
// The behavior is:
// - If `-fmodule-output=` is specfied, then the module file is
// writing to the value.
// - Otherwise if the output object file of the module unit is specified, the
// output path
// of the module file should be the same with the output object file except
// the corresponding suffix. This requires both `-o` and `-c` are specified.
// - Otherwise, the output path of the module file will be the same with the
// input with the corresponding suffix.
llvm::SmallString<256>
getCXX20NamedModuleOutputPath(const llvm::opt::ArgList &Args,
const char *BaseInput);

} // end namespace tools

} // end namespace driver
Expand Down
58 changes: 22 additions & 36 deletions clang/lib/Driver/ToolChains/CommonArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1075,53 +1075,38 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args,

/// Adds the '-lcgpu' and '-lmgpu' libraries to the compilation to include the
/// LLVM C library for GPUs.
static void addOpenMPDeviceLibC(const ToolChain &TC, const ArgList &Args,
static void addOpenMPDeviceLibC(const Compilation &C, const ArgList &Args,
ArgStringList &CmdArgs) {
if (Args.hasArg(options::OPT_nogpulib) || Args.hasArg(options::OPT_nolibc))
return;

// Check the resource directory for the LLVM libc GPU declarations. If it's
// found we can assume that LLVM was built with support for the GPU libc.
SmallString<256> LibCDecls(TC.getDriver().ResourceDir);
SmallString<256> LibCDecls(C.getDriver().ResourceDir);
llvm::sys::path::append(LibCDecls, "include", "llvm_libc_wrappers",
"llvm-libc-decls");
bool HasLibC = llvm::sys::fs::exists(LibCDecls) &&
llvm::sys::fs::is_directory(LibCDecls);
if (!Args.hasFlag(options::OPT_gpulibc, options::OPT_nogpulibc, HasLibC))
return;

// We don't have access to the offloading toolchains here, so determine from
// the arguments if we have any active NVPTX or AMDGPU toolchains.
llvm::DenseSet<const char *> Libraries;
if (const Arg *Targets = Args.getLastArg(options::OPT_fopenmp_targets_EQ)) {
if (llvm::any_of(Targets->getValues(),
[](auto S) { return llvm::Triple(S).isAMDGPU(); })) {
Libraries.insert("-lcgpu-amdgpu");
Libraries.insert("-lmgpu-amdgpu");
}
if (llvm::any_of(Targets->getValues(),
[](auto S) { return llvm::Triple(S).isNVPTX(); })) {
Libraries.insert("-lcgpu-nvptx");
Libraries.insert("-lmgpu-nvptx");
}
}
SmallVector<const ToolChain *> ToolChains;
auto TCRange = C.getOffloadToolChains(Action::OFK_OpenMP);
for (auto TI = TCRange.first, TE = TCRange.second; TI != TE; ++TI)
ToolChains.push_back(TI->second);

for (StringRef Arch : Args.getAllArgValues(options::OPT_offload_arch_EQ)) {
if (llvm::any_of(llvm::split(Arch, ","), [](StringRef Str) {
return IsAMDGpuArch(StringToCudaArch(Str));
})) {
Libraries.insert("-lcgpu-amdgpu");
Libraries.insert("-lmgpu-amdgpu");
}
if (llvm::any_of(llvm::split(Arch, ","), [](StringRef Str) {
return IsNVIDIAGpuArch(StringToCudaArch(Str));
})) {
Libraries.insert("-lcgpu-nvptx");
Libraries.insert("-lmgpu-nvptx");
}
if (llvm::any_of(ToolChains, [](const ToolChain *TC) {
return TC->getTriple().isAMDGPU();
})) {
CmdArgs.push_back("-lcgpu-amdgpu");
CmdArgs.push_back("-lmgpu-amdgpu");
}
if (llvm::any_of(ToolChains, [](const ToolChain *TC) {
return TC->getTriple().isNVPTX();
})) {
CmdArgs.push_back("-lcgpu-nvptx");
CmdArgs.push_back("-lmgpu-nvptx");
}

llvm::append_range(CmdArgs, Libraries);
}

void tools::addOpenMPRuntimeLibraryPath(const ToolChain &TC,
Expand Down Expand Up @@ -1153,9 +1138,10 @@ void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args,
}
}

bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC,
const ArgList &Args, bool ForceStaticHostRuntime,
bool IsOffloadingHost, bool GompNeedsRT) {
bool tools::addOpenMPRuntime(const Compilation &C, ArgStringList &CmdArgs,
const ToolChain &TC, const ArgList &Args,
bool ForceStaticHostRuntime, bool IsOffloadingHost,
bool GompNeedsRT) {
if (!Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
options::OPT_fno_openmp, false))
return false;
Expand Down Expand Up @@ -1196,7 +1182,7 @@ bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC,
CmdArgs.push_back("-lomptarget.devicertl");

if (IsOffloadingHost)
addOpenMPDeviceLibC(TC, Args, CmdArgs);
addOpenMPDeviceLibC(C, Args, CmdArgs);

addArchSpecificRPath(TC, Args, CmdArgs);
addOpenMPRuntimeLibraryPath(TC, Args, CmdArgs);
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Driver/ToolChains/CommonArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ void addOpenMPRuntimeLibraryPath(const ToolChain &TC,
const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs);
/// Returns true, if an OpenMP runtime has been added.
bool addOpenMPRuntime(llvm::opt::ArgStringList &CmdArgs, const ToolChain &TC,
const llvm::opt::ArgList &Args,
bool addOpenMPRuntime(const Compilation &C, llvm::opt::ArgStringList &CmdArgs,
const ToolChain &TC, const llvm::opt::ArgList &Args,
bool ForceStaticHostRuntime = false,
bool IsOffloadingHost = false, bool GompNeedsRT = false);

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/Darwin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,7 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}

if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
addOpenMPRuntime(CmdArgs, getToolChain(), Args);
addOpenMPRuntime(C, CmdArgs, getToolChain(), Args);

if (isObjCRuntimeLinked(Args) &&
!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/DragonFly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,

// Use the static OpenMP runtime with -static-openmp
bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && !Static;
addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP);
addOpenMPRuntime(C, CmdArgs, ToolChain, Args, StaticOpenMP);

if (D.CCCIsCXX()) {
if (ToolChain.ShouldLinkCXXStdlib(Args))
Expand Down
62 changes: 41 additions & 21 deletions clang/lib/Driver/ToolChains/Flang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,27 +35,18 @@ static void addDashXForInput(const ArgList &Args, const InputInfo &Input,

void Flang::addFortranDialectOptions(const ArgList &Args,
ArgStringList &CmdArgs) const {
Args.addAllArgs(CmdArgs, {options::OPT_ffixed_form,
options::OPT_ffree_form,
options::OPT_ffixed_line_length_EQ,
options::OPT_fopenmp,
options::OPT_fopenmp_version_EQ,
options::OPT_fopenacc,
options::OPT_finput_charset_EQ,
options::OPT_fimplicit_none,
options::OPT_fno_implicit_none,
options::OPT_fbackslash,
options::OPT_fno_backslash,
options::OPT_flogical_abbreviations,
options::OPT_fno_logical_abbreviations,
options::OPT_fxor_operator,
options::OPT_fno_xor_operator,
options::OPT_falternative_parameter_statement,
options::OPT_fdefault_real_8,
options::OPT_fdefault_integer_8,
options::OPT_fdefault_double_8,
options::OPT_flarge_sizes,
options::OPT_fno_automatic});
Args.addAllArgs(
CmdArgs, {options::OPT_ffixed_form, options::OPT_ffree_form,
options::OPT_ffixed_line_length_EQ, options::OPT_fopenacc,
options::OPT_finput_charset_EQ, options::OPT_fimplicit_none,
options::OPT_fno_implicit_none, options::OPT_fbackslash,
options::OPT_fno_backslash, options::OPT_flogical_abbreviations,
options::OPT_fno_logical_abbreviations,
options::OPT_fxor_operator, options::OPT_fno_xor_operator,
options::OPT_falternative_parameter_statement,
options::OPT_fdefault_real_8, options::OPT_fdefault_integer_8,
options::OPT_fdefault_double_8, options::OPT_flarge_sizes,
options::OPT_fno_automatic});
}

void Flang::addPreprocessingOptions(const ArgList &Args,
Expand Down Expand Up @@ -763,6 +754,35 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
// Add other compile options
addOtherOptions(Args, CmdArgs);

// Forward flags for OpenMP. We don't do this if the current action is an
// device offloading action other than OpenMP.
if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
options::OPT_fno_openmp, false) &&
(JA.isDeviceOffloading(Action::OFK_None) ||
JA.isDeviceOffloading(Action::OFK_OpenMP))) {
switch (D.getOpenMPRuntime(Args)) {
case Driver::OMPRT_OMP:
case Driver::OMPRT_IOMP5:
// Clang can generate useful OpenMP code for these two runtime libraries.
CmdArgs.push_back("-fopenmp");
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_version_EQ);

// FIXME: Clang supports a whole bunch more flags here.
break;
default:
// By default, if Clang doesn't know how to generate useful OpenMP code
// for a specific runtime library, we just don't pass the '-fopenmp' flag
// down to the actual compilation.
// FIXME: It would be better to have a mode which *only* omits IR
// generation based on the OpenMP support so that we get consistent
// semantic analysis, etc.
const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ);
D.Diag(diag::warn_drv_unsupported_openmp_library)
<< A->getSpelling() << A->getValue();
break;
}
}

// Offloading related options
addOffloadOptions(C, Inputs, JA, Args, CmdArgs);

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/FreeBSD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// Use the static OpenMP runtime with -static-openmp
bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) &&
!Args.hasArg(options::OPT_static);
addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP);
addOpenMPRuntime(C, CmdArgs, ToolChain, Args, StaticOpenMP);

if (D.CCCIsCXX()) {
if (ToolChain.ShouldLinkCXXStdlib(Args))
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 @@ -598,7 +598,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,

// FIXME: Only pass GompNeedsRT = true for platforms with libgomp that
// require librt. Most modern Linux platforms do, but some may not.
if (addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP,
if (addOpenMPRuntime(C, CmdArgs, ToolChain, Args, StaticOpenMP,
JA.isHostOffloading(Action::OFK_OpenMP),
/* GompNeedsRT= */ true))
// OpenMP runtimes implies pthreads when using the GNU toolchain.
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/Haiku.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ void haiku::Linker::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_r)) {
// Use the static OpenMP runtime with -static-openmp
bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && !Static;
addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP);
addOpenMPRuntime(C, CmdArgs, ToolChain, Args, StaticOpenMP);

if (D.CCCIsCXX() && ToolChain.ShouldLinkCXXStdlib(Args))
ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/NetBSD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_r)) {
// Use the static OpenMP runtime with -static-openmp
bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && !Static;
addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP);
addOpenMPRuntime(C, CmdArgs, ToolChain, Args, StaticOpenMP);

if (D.CCCIsCXX()) {
if (ToolChain.ShouldLinkCXXStdlib(Args))
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/OpenBSD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_r)) {
// Use the static OpenMP runtime with -static-openmp
bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && !Static;
addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP);
addOpenMPRuntime(C, CmdArgs, ToolChain, Args, StaticOpenMP);

if (D.CCCIsCXX()) {
if (ToolChain.ShouldLinkCXXStdlib(Args))
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/Solaris.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// Use the static OpenMP runtime with -static-openmp
bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) &&
!Args.hasArg(options::OPT_static);
addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP);
addOpenMPRuntime(C, CmdArgs, ToolChain, Args, StaticOpenMP);

if (D.CCCIsCXX()) {
if (ToolChain.ShouldLinkCXXStdlib(Args))
Expand Down
544 changes: 53 additions & 491 deletions clang/lib/ExtractAPI/API.cpp

Large diffs are not rendered by default.

122 changes: 56 additions & 66 deletions clang/lib/ExtractAPI/DeclarationFragments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,11 @@
#include "clang/ExtractAPI/DeclarationFragments.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/QualTypeNames.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"
#include "clang/Index/USRGeneration.h"
#include "llvm/ADT/StringSwitch.h"
#include <typeinfo>

using namespace clang::extractapi;
using namespace llvm;
Expand Down Expand Up @@ -60,23 +57,44 @@ void findTypeLocForBlockDecl(const clang::TypeSourceInfo *TSInfo,

} // namespace

DeclarationFragments &DeclarationFragments::appendSpace() {
DeclarationFragments &
DeclarationFragments::appendUnduplicatedTextCharacter(char Character) {
if (!Fragments.empty()) {
Fragment &Last = Fragments.back();
if (Last.Kind == FragmentKind::Text) {
// Merge the extra space into the last fragment if the last fragment is
// also text.
if (Last.Spelling.back() != ' ') { // avoid extra trailing spaces.
Last.Spelling.push_back(' ');
if (Last.Spelling.back() != Character) { // avoid duplicates at end
Last.Spelling.push_back(Character);
}
} else {
append(" ", FragmentKind::Text);
append("", FragmentKind::Text);
Fragments.back().Spelling.push_back(Character);
}
}

return *this;
}

DeclarationFragments &DeclarationFragments::appendSpace() {
return appendUnduplicatedTextCharacter(' ');
}

DeclarationFragments &DeclarationFragments::appendSemicolon() {
return appendUnduplicatedTextCharacter(';');
}

DeclarationFragments &DeclarationFragments::removeTrailingSemicolon() {
if (Fragments.empty())
return *this;

Fragment &Last = Fragments.back();
if (Last.Kind == FragmentKind::Text && Last.Spelling.back() == ';')
Last.Spelling.pop_back();

return *this;
}

StringRef DeclarationFragments::getFragmentKindString(
DeclarationFragments::FragmentKind Kind) {
switch (Kind) {
Expand Down Expand Up @@ -469,7 +487,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForNamespace(
if (!Decl->isAnonymousNamespace())
Fragments.appendSpace().append(
Decl->getName(), DeclarationFragments::FragmentKind::Identifier);
return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
return Fragments.appendSemicolon();
}

DeclarationFragments
Expand Down Expand Up @@ -511,7 +529,7 @@ DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) {
return Fragments
.append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
.append(std::move(After))
.append(";", DeclarationFragments::FragmentKind::Text);
.appendSemicolon();
}

DeclarationFragments
Expand All @@ -535,15 +553,13 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplate(const VarDecl *Var) {
getFragmentsForType(T, Var->getASTContext(), After);
if (StringRef(ArgumentFragment.begin()->Spelling)
.starts_with("type-parameter")) {
std::string ProperArgName = getNameForTemplateArgument(
Var->getDescribedVarTemplate()->getTemplateParameters()->asArray(),
ArgumentFragment.begin()->Spelling);
std::string ProperArgName = T.getAsString();
ArgumentFragment.begin()->Spelling.swap(ProperArgName);
}
Fragments.append(std::move(ArgumentFragment))
.appendSpace()
.append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
.append(";", DeclarationFragments::FragmentKind::Text);
.appendSemicolon();
return Fragments;
}

Expand All @@ -570,12 +586,7 @@ DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) {

if (StringRef(TypeFragments.begin()->Spelling)
.starts_with("type-parameter")) {
std::string ProperArgName = getNameForTemplateArgument(
dyn_cast<FunctionDecl>(Param->getDeclContext())
->getDescribedFunctionTemplate()
->getTemplateParameters()
->asArray(),
TypeFragments.begin()->Spelling);
std::string ProperArgName = Param->getOriginalType().getAsString();
TypeFragments.begin()->Spelling.swap(ProperArgName);
}

Expand Down Expand Up @@ -668,11 +679,7 @@ DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) {
getFragmentsForType(Func->getReturnType(), Func->getASTContext(), After);
if (StringRef(ReturnValueFragment.begin()->Spelling)
.starts_with("type-parameter")) {
std::string ProperArgName =
getNameForTemplateArgument(Func->getDescribedFunctionTemplate()
->getTemplateParameters()
->asArray(),
ReturnValueFragment.begin()->Spelling);
std::string ProperArgName = Func->getReturnType().getAsString();
ReturnValueFragment.begin()->Spelling.swap(ProperArgName);
}

Expand Down Expand Up @@ -712,7 +719,7 @@ DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) {
Fragments.append(DeclarationFragments::getExceptionSpecificationString(
Func->getExceptionSpecType()));

return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
return Fragments.appendSemicolon();
}

DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant(
Expand Down Expand Up @@ -741,7 +748,7 @@ DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) {
getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After))
.append(std::move(After));

return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
return Fragments.appendSemicolon();
}

DeclarationFragments
Expand All @@ -757,7 +764,7 @@ DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) {
.appendSpace()
.append(Field->getName(), DeclarationFragments::FragmentKind::Identifier)
.append(std::move(After))
.append(";", DeclarationFragments::FragmentKind::Text);
.appendSemicolon();
}

DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForRecordDecl(
Expand All @@ -775,7 +782,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForRecordDecl(
Fragments.appendSpace().append(
Record->getName(), DeclarationFragments::FragmentKind::Identifier);

return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
return Fragments.appendSemicolon();
}

DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass(
Expand All @@ -790,7 +797,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass(
Fragments.appendSpace().append(
Record->getName(), DeclarationFragments::FragmentKind::Identifier);

return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
return Fragments.appendSemicolon();
}

DeclarationFragments
Expand Down Expand Up @@ -820,7 +827,7 @@ DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod(
Fragments.append(DeclarationFragments::getExceptionSpecificationString(
Method->getExceptionSpecType()));

return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
return Fragments.appendSemicolon();
}

DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod(
Expand Down Expand Up @@ -860,7 +867,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod(
Fragments.append(DeclarationFragments::getExceptionSpecificationString(
Method->getExceptionSpecType()));

return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
return Fragments.appendSemicolon();
}

DeclarationFragments
Expand Down Expand Up @@ -891,7 +898,7 @@ DeclarationFragmentsBuilder::getFragmentsForConversionFunction(
Fragments.appendSpace().append("const",
DeclarationFragments::FragmentKind::Keyword);

return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
return Fragments.appendSemicolon();
}

DeclarationFragments
Expand Down Expand Up @@ -923,7 +930,7 @@ DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(
Fragments.append(DeclarationFragments::getExceptionSpecificationString(
Method->getExceptionSpecType()));

return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
return Fragments.appendSemicolon();
}

// Get fragments for template parameters, e.g. T in tempalte<typename T> ...
Expand Down Expand Up @@ -961,25 +968,6 @@ DeclarationFragmentsBuilder::getFragmentsForTemplateParameters(
return Fragments;
}

// Find the name of a template argument from the template's parameters.
std::string DeclarationFragmentsBuilder::getNameForTemplateArgument(
const ArrayRef<NamedDecl *> TemplateParameters, std::string TypeParameter) {
// The arg is a generic parameter from a partial spec, e.g.
// T in template<typename T> Foo<T, int>.
//
// Those names appear as "type-parameter-<index>-<depth>", so we must find its
// name from the template's parameter list.
for (unsigned i = 0; i < TemplateParameters.size(); ++i) {
const auto *Parameter =
dyn_cast<TemplateTypeParmDecl>(TemplateParameters[i]);
if (TypeParameter.compare("type-parameter-" +
std::to_string(Parameter->getDepth()) + "-" +
std::to_string(Parameter->getIndex())) == 0)
return std::string(TemplateParameters[i]->getName());
}
llvm_unreachable("Could not find the name of a template argument.");
}

// Get fragments for template arguments, e.g. int in template<typename T>
// Foo<int>;
//
Expand All @@ -989,7 +977,7 @@ std::string DeclarationFragmentsBuilder::getNameForTemplateArgument(
DeclarationFragments
DeclarationFragmentsBuilder::getFragmentsForTemplateArguments(
const ArrayRef<TemplateArgument> TemplateArguments, ASTContext &Context,
const std::optional<ArrayRef<NamedDecl *>> TemplateParameters) {
const std::optional<ArrayRef<TemplateArgumentLoc>> TemplateArgumentLocs) {
DeclarationFragments Fragments;
for (unsigned i = 0, end = TemplateArguments.size(); i != end; ++i) {
if (i)
Expand All @@ -1003,8 +991,10 @@ DeclarationFragmentsBuilder::getFragmentsForTemplateArguments(

if (StringRef(ArgumentFragment.begin()->Spelling)
.starts_with("type-parameter")) {
std::string ProperArgName = getNameForTemplateArgument(
TemplateParameters.value(), ArgumentFragment.begin()->Spelling);
std::string ProperArgName = TemplateArgumentLocs.value()[i]
.getTypeSourceInfo()
->getType()
.getAsString();
ArgumentFragment.begin()->Spelling.swap(ProperArgName);
}
Fragments.append(std::move(ArgumentFragment));
Expand All @@ -1028,7 +1018,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForConcept(
.appendSpace()
.append(Concept->getName().str(),
DeclarationFragments::FragmentKind::Identifier)
.append(";", DeclarationFragments::FragmentKind::Text);
.appendSemicolon();
}

DeclarationFragments
Expand Down Expand Up @@ -1069,7 +1059,7 @@ DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization(
getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(),
Decl->getASTContext(), std::nullopt))
.append(">", DeclarationFragments::FragmentKind::Text)
.append(";", DeclarationFragments::FragmentKind::Text);
.appendSemicolon();
}

DeclarationFragments
Expand All @@ -1089,9 +1079,9 @@ DeclarationFragmentsBuilder::getFragmentsForClassTemplatePartialSpecialization(
.append("<", DeclarationFragments::FragmentKind::Text)
.append(getFragmentsForTemplateArguments(
Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
Decl->getTemplateParameters()->asArray()))
Decl->getTemplateArgsAsWritten()->arguments()))
.append(">", DeclarationFragments::FragmentKind::Text)
.append(";", DeclarationFragments::FragmentKind::Text);
.appendSemicolon();
}

DeclarationFragments
Expand All @@ -1110,7 +1100,7 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization(
getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(),
Decl->getASTContext(), std::nullopt))
.append(">", DeclarationFragments::FragmentKind::Text)
.append(";", DeclarationFragments::FragmentKind::Text);
.appendSemicolon();
}

DeclarationFragments
Expand All @@ -1130,9 +1120,9 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplatePartialSpecialization(
.append("<", DeclarationFragments::FragmentKind::Text)
.append(getFragmentsForTemplateArguments(
Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
Decl->getTemplateParameters()->asArray()))
Decl->getTemplateArgsAsWritten()->arguments()))
.append(">", DeclarationFragments::FragmentKind::Text)
.append(";", DeclarationFragments::FragmentKind::Text);
.appendSemicolon();
}

DeclarationFragments
Expand Down Expand Up @@ -1203,7 +1193,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCCategory(

Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)
.appendSpace()
.append(Category->getClassInterface()->getName(),
.append(Interface->getName(),
DeclarationFragments::FragmentKind::TypeIdentifier, InterfaceUSR,
Interface)
.append(" (", DeclarationFragments::FragmentKind::Text)
Expand Down Expand Up @@ -1277,7 +1267,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod(
Fragments.append(getFragmentsForParam(Param));
}

return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
return Fragments.appendSemicolon();
}

DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty(
Expand Down Expand Up @@ -1378,7 +1368,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty(
.append(Property->getName(),
DeclarationFragments::FragmentKind::Identifier)
.append(std::move(After))
.append(";", DeclarationFragments::FragmentKind::Text);
.appendSemicolon();
}

DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol(
Expand Down Expand Up @@ -1422,7 +1412,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef(
.appendSpace()
.append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier);

return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
return Fragments.appendSemicolon();
}

// Instantiate template for FunctionDecl.
Expand Down
112 changes: 53 additions & 59 deletions clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Frontend/MultiplexConsumer.h"
#include "clang/Index/USRGeneration.h"
#include "clang/InstallAPI/HeaderFile.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/PPCallbacks.h"
Expand All @@ -39,6 +40,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
Expand Down Expand Up @@ -327,11 +329,12 @@ class MacroCallback : public PPCallbacks {

StringRef Name = PM.MacroNameToken.getIdentifierInfo()->getName();
PresumedLoc Loc = SM.getPresumedLoc(PM.MacroNameToken.getLocation());
StringRef USR =
API.recordUSRForMacro(Name, PM.MacroNameToken.getLocation(), SM);
SmallString<128> USR;
index::generateUSRForMacro(Name, PM.MacroNameToken.getLocation(), SM,
USR);

API.addMacroDefinition(
Name, USR, Loc,
API.createRecord<extractapi::MacroDefinitionRecord>(
USR, Name, SymbolReference(), Loc,
DeclarationFragmentsBuilder::getFragmentsForMacro(Name, PM.MD),
DeclarationFragmentsBuilder::getSubHeadingForMacro(Name),
SM.isInSystemHeader(PM.MacroNameToken.getLocation()));
Expand Down Expand Up @@ -372,40 +375,57 @@ class APIMacroCallback : public MacroCallback {
LocationFileChecker &LCF;
};

std::unique_ptr<llvm::raw_pwrite_stream>
createAdditionalSymbolGraphFile(CompilerInstance &CI, Twine BaseName) {
auto OutputDirectory = CI.getFrontendOpts().SymbolGraphOutputDir;

SmallString<256> FileName;
llvm::sys::path::append(FileName, OutputDirectory,
BaseName + ".symbols.json");
return CI.createOutputFile(
FileName, /*Binary*/ false, /*RemoveFileOnSignal*/ false,
/*UseTemporary*/ true, /*CreateMissingDirectories*/ true);
}

} // namespace

void ExtractAPIActionBase::ImplEndSourceFileAction() {
if (!OS)
return;
void ExtractAPIActionBase::ImplEndSourceFileAction(CompilerInstance &CI) {
SymbolGraphSerializerOption SerializationOptions;
SerializationOptions.Compact = !CI.getFrontendOpts().EmitPrettySymbolGraphs;
SerializationOptions.EmitSymbolLabelsForTesting =
CI.getFrontendOpts().EmitSymbolGraphSymbolLabelsForTesting;

if (CI.getFrontendOpts().EmitExtensionSymbolGraphs) {
auto ConstructOutputFile = [&CI](Twine BaseName) {
return createAdditionalSymbolGraphFile(CI, BaseName);
};

SymbolGraphSerializer::serializeWithExtensionGraphs(
*OS, *API, IgnoresList, ConstructOutputFile, SerializationOptions);
} else {
SymbolGraphSerializer::serializeMainSymbolGraph(*OS, *API, IgnoresList,
SerializationOptions);
}

// Setup a SymbolGraphSerializer to write out collected API information in
// the Symbol Graph format.
// FIXME: Make the kind of APISerializer configurable.
SymbolGraphSerializer SGSerializer(*API, IgnoresList);
SGSerializer.serialize(*OS);
// Flush the stream and close the main output stream.
OS.reset();
}

std::unique_ptr<raw_pwrite_stream>
ExtractAPIAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile) {
std::unique_ptr<raw_pwrite_stream> OS;
OS = CI.createDefaultOutputFile(/*Binary=*/false, InFile,
/*Extension=*/"json",
/*RemoveFileOnSignal=*/false);
if (!OS)
return nullptr;
return OS;
}

std::unique_ptr<ASTConsumer>
ExtractAPIAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
OS = CreateOutputFile(CI, InFile);
auto ProductName = CI.getFrontendOpts().ProductName;

if (CI.getFrontendOpts().SymbolGraphOutputDir.empty())
OS = CI.createDefaultOutputFile(/*Binary*/ false, InFile,
/*Extension*/ "symbols.json",
/*RemoveFileOnSignal*/ false,
/*CreateMissingDirectories*/ true);
else
OS = createAdditionalSymbolGraphFile(CI, ProductName);

if (!OS)
return nullptr;

auto ProductName = CI.getFrontendOpts().ProductName;

// Now that we have enough information about the language options and the
// target triple, let's create the APISet before anyone uses it.
API = std::make_unique<APISet>(
Expand Down Expand Up @@ -495,7 +515,9 @@ bool ExtractAPIAction::PrepareToExecuteAction(CompilerInstance &CI) {
return true;
}

void ExtractAPIAction::EndSourceFileAction() { ImplEndSourceFileAction(); }
void ExtractAPIAction::EndSourceFileAction() {
ImplEndSourceFileAction(getCompilerInstance());
}

std::unique_ptr<ASTConsumer>
WrappingExtractAPIAction::CreateASTConsumer(CompilerInstance &CI,
Expand All @@ -506,11 +528,9 @@ WrappingExtractAPIAction::CreateASTConsumer(CompilerInstance &CI,

CreatedASTConsumer = true;

OS = CreateOutputFile(CI, InFile);
if (!OS)
return nullptr;

auto ProductName = CI.getFrontendOpts().ProductName;
ProductName = CI.getFrontendOpts().ProductName;
auto InputFilename = llvm::sys::path::filename(InFile);
OS = createAdditionalSymbolGraphFile(CI, InputFilename);

// Now that we have enough information about the language options and the
// target triple, let's create the APISet before anyone uses it.
Expand Down Expand Up @@ -552,32 +572,6 @@ void WrappingExtractAPIAction::EndSourceFileAction() {
WrapperFrontendAction::EndSourceFileAction();

if (CreatedASTConsumer) {
ImplEndSourceFileAction();
ImplEndSourceFileAction(getCompilerInstance());
}
}

std::unique_ptr<raw_pwrite_stream>
WrappingExtractAPIAction::CreateOutputFile(CompilerInstance &CI,
StringRef InFile) {
std::unique_ptr<raw_pwrite_stream> OS;
std::string OutputDir = CI.getFrontendOpts().SymbolGraphOutputDir;

// The symbol graphs need to be generated as a side effect of regular
// compilation so the output should be dumped in the directory provided with
// the command line option.
llvm::SmallString<128> OutFilePath(OutputDir);
auto Seperator = llvm::sys::path::get_separator();
auto Infilename = llvm::sys::path::filename(InFile);
OutFilePath.append({Seperator, Infilename});
llvm::sys::path::replace_extension(OutFilePath, "json");
// StringRef outputFilePathref = *OutFilePath;

// don't use the default output file
OS = CI.createOutputFile(/*OutputPath=*/OutFilePath, /*Binary=*/false,
/*RemoveFileOnSignal=*/true,
/*UseTemporary=*/true,
/*CreateMissingDirectories=*/true);
if (!OS)
return nullptr;
return OS;
}
943 changes: 379 additions & 564 deletions clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//

#include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"
#include "clang/Basic/Module.h"
#include "clang/Index/USRGeneration.h"

using namespace clang;
Expand Down Expand Up @@ -50,17 +51,20 @@ TypedefUnderlyingTypeResolver::getSymbolReferenceForType(QualType Type,
SmallString<128> TypeUSR;
const NamedDecl *TypeDecl = getUnderlyingTypeDecl(Type);
const TypedefType *TypedefTy = Type->getAs<TypedefType>();
StringRef OwningModuleName;

if (TypeDecl) {
if (!TypedefTy)
TypeName = TypeDecl->getName().str();

clang::index::generateUSRForDecl(TypeDecl, TypeUSR);
if (auto *OwningModule = TypeDecl->getImportedOwningModule())
OwningModuleName = OwningModule->Name;
} else {
clang::index::generateUSRForType(Type, Context, TypeUSR);
}

return {API.copyString(TypeName), API.copyString(TypeUSR)};
return API.createSymbolReference(TypeName, TypeUSR, OwningModuleName);
}

std::string TypedefUnderlyingTypeResolver::getUSRForType(QualType Type) const {
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/Format/Format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -955,6 +955,8 @@ template <> struct MappingTraits<FormatStyle> {
Style.BreakBeforeTernaryOperators);
IO.mapOptional("BreakConstructorInitializers",
Style.BreakConstructorInitializers);
IO.mapOptional("BreakFunctionDefinitionParameters",
Style.BreakFunctionDefinitionParameters);
IO.mapOptional("BreakInheritanceList", Style.BreakInheritanceList);
IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals);
IO.mapOptional("BreakTemplateDeclarations",
Expand Down Expand Up @@ -1465,6 +1467,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.BreakBeforeInlineASMColon = FormatStyle::BBIAS_OnlyMultiline;
LLVMStyle.BreakBeforeTernaryOperators = true;
LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
LLVMStyle.BreakFunctionDefinitionParameters = false;
LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
LLVMStyle.BreakStringLiterals = true;
LLVMStyle.BreakTemplateDeclarations = FormatStyle::BTDS_MultiLine;
Expand Down Expand Up @@ -3578,7 +3581,7 @@ cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces,
// We need to use lambda function here since there are two versions of
// `cleanup`.
auto Cleanup = [](const FormatStyle &Style, StringRef Code,
std::vector<tooling::Range> Ranges,
ArrayRef<tooling::Range> Ranges,
StringRef FileName) -> tooling::Replacements {
return cleanup(Style, Code, Ranges, FileName);
};
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Format/FormatToken.h
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,9 @@ struct FormatToken {
/// Is optional and can be removed.
bool Optional = false;

/// Might be function declaration open/closing paren.
bool MightBeFunctionDeclParen = false;

/// Number of optional braces to be inserted after this token:
/// -1: a single left brace
/// 0: no braces
Expand Down
9 changes: 9 additions & 0 deletions clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1550,6 +1550,7 @@ class AnnotatingParser {
(!Previous->isAttribute() &&
!Previous->isOneOf(TT_RequiresClause, TT_LeadingJavaAnnotation))) {
Line.MightBeFunctionDecl = true;
Tok->MightBeFunctionDeclParen = true;
}
}
break;
Expand Down Expand Up @@ -3888,6 +3889,8 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
}
} else if (ClosingParen) {
for (auto *Tok = ClosingParen->Next; Tok; Tok = Tok->Next) {
if (Tok->is(TT_CtorInitializerColon))
break;
if (Tok->is(tok::arrow)) {
Tok->setType(TT_TrailingReturnArrow);
break;
Expand Down Expand Up @@ -5392,6 +5395,12 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
if (Right.NewlinesBefore > 1 && Style.MaxEmptyLinesToKeep > 0)
return true;

if (Style.BreakFunctionDefinitionParameters && Line.MightBeFunctionDecl &&
Line.mightBeFunctionDefinition() && Left.MightBeFunctionDeclParen &&
Left.ParameterCount > 0) {
return true;
}

if (Style.isCSharp()) {
if (Left.is(TT_FatArrow) && Right.is(tok::l_brace) &&
Style.BraceWrapping.AfterFunction) {
Expand Down
17 changes: 10 additions & 7 deletions clang/lib/Format/UnwrappedLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -495,20 +495,22 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
};
SmallVector<StackEntry, 8> LBraceStack;
assert(Tok->is(tok::l_brace));

do {
// Get next non-comment, non-preprocessor token.
FormatToken *NextTok;
do {
NextTok = Tokens->getNextToken();
} while (NextTok->is(tok::comment));
if (!Style.isTableGen()) {
// InTableGen, '#' is like binary operator. Not a preprocessor directive.
while (NextTok->is(tok::hash) && !Line->InMacroBody) {
NextTok = Tokens->getNextToken();

if (!Line->InMacroBody && !Style.isTableGen()) {
// Skip PPDirective lines and comments.
while (NextTok->is(tok::hash)) {
do {
NextTok = Tokens->getNextToken();
} while (NextTok->is(tok::comment) ||
(NextTok->NewlinesBefore == 0 && NextTok->isNot(tok::eof)));
} while (NextTok->NewlinesBefore == 0 && NextTok->isNot(tok::eof));

while (NextTok->is(tok::comment))
NextTok = Tokens->getNextToken();
}
}

Expand Down Expand Up @@ -640,6 +642,7 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
default:
break;
}

PrevTok = Tok;
Tok = NextTok;
} while (Tok->isNot(tok::eof) && !LBraceStack.empty());
Expand Down
21 changes: 11 additions & 10 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -533,10 +533,10 @@ static T extractMaskValue(T KeyPath) {

#define PARSE_OPTION_WITH_MARSHALLING( \
ARGS, DIAGS, PREFIX_TYPE, SPELLING, ID, KIND, GROUP, ALIAS, ALIASARGS, \
FLAGS, VISIBILITY, PARAM, HELPTEXT, METAVAR, VALUES, SHOULD_PARSE, \
ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, \
NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX) \
if ((VISIBILITY)&options::CC1Option) { \
FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES, \
SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK, \
IMPLIED_VALUE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX) \
if ((VISIBILITY) & options::CC1Option) { \
KEYPATH = MERGER(KEYPATH, DEFAULT_VALUE); \
if (IMPLIED_CHECK) \
KEYPATH = MERGER(KEYPATH, IMPLIED_VALUE); \
Expand All @@ -550,10 +550,10 @@ static T extractMaskValue(T KeyPath) {
// with lifetime extension of the reference.
#define GENERATE_OPTION_WITH_MARSHALLING( \
CONSUMER, PREFIX_TYPE, SPELLING, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, \
VISIBILITY, PARAM, HELPTEXT, METAVAR, VALUES, SHOULD_PARSE, ALWAYS_EMIT, \
KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, \
DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX) \
if ((VISIBILITY)&options::CC1Option) { \
VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES, \
SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK, \
IMPLIED_VALUE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX) \
if ((VISIBILITY) & options::CC1Option) { \
[&](const auto &Extracted) { \
if (ALWAYS_EMIT || \
(Extracted != \
Expand Down Expand Up @@ -3516,7 +3516,8 @@ void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts,
GenerateArg(Consumer, OPT_fblocks);

if (Opts.ConvergentFunctions &&
!(Opts.OpenCL || (Opts.CUDA && Opts.CUDAIsDevice) || Opts.SYCLIsDevice))
!(Opts.OpenCL || (Opts.CUDA && Opts.CUDAIsDevice) || Opts.SYCLIsDevice ||
Opts.HLSL))
GenerateArg(Consumer, OPT_fconvergent_functions);

if (Opts.NoBuiltin && !Opts.Freestanding)
Expand Down Expand Up @@ -3914,7 +3915,7 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,

Opts.ConvergentFunctions = Args.hasArg(OPT_fconvergent_functions) ||
Opts.OpenCL || (Opts.CUDA && Opts.CUDAIsDevice) ||
Opts.SYCLIsDevice;
Opts.SYCLIsDevice || Opts.HLSL;

Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding;
if (!Opts.NoBuiltin)
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Frontend/FrontendActions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,8 @@ class DefaultTemplateInstCallback : public TemplateInstantiationCallback {
return "BuildingBuiltinDumpStructCall";
case CodeSynthesisContext::BuildingDeductionGuides:
return "BuildingDeductionGuides";
case Sema::CodeSynthesisContext::TypeAliasTemplateInstantiation:
return "TypeAliasTemplateInstantiation";
}
return "";
}
Expand Down
3 changes: 1 addition & 2 deletions clang/lib/Frontend/PrecompiledPreamble.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,8 +290,7 @@ class PrecompilePreambleAction : public ASTFrontendAction {

class PrecompilePreambleConsumer : public PCHGenerator {
public:
PrecompilePreambleConsumer(PrecompilePreambleAction &Action,
const Preprocessor &PP,
PrecompilePreambleConsumer(PrecompilePreambleAction &Action, Preprocessor &PP,
InMemoryModuleCache &ModuleCache,
StringRef isysroot,
std::shared_ptr<PCHBuffer> Buffer)
Expand Down
10 changes: 7 additions & 3 deletions clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,13 @@ CreateFrontendAction(CompilerInstance &CI) {
#endif

// Wrap the base FE action in an extract api action to generate
// symbol graph as a biproduct of compilation ( enabled with
// --emit-symbol-graph option )
if (!FEOpts.SymbolGraphOutputDir.empty()) {
// symbol graph as a biproduct of compilation (enabled with
// --emit-symbol-graph option)
if (FEOpts.EmitSymbolGraph) {
if (FEOpts.SymbolGraphOutputDir.empty()) {
CI.getDiagnostics().Report(diag::warn_missing_symbol_graph_dir);
CI.getFrontendOpts().SymbolGraphOutputDir = ".";
}
CI.getCodeGenOpts().ClearASTBeforeBackend = false;
Act = std::make_unique<WrappingExtractAPIAction>(std::move(Act));
}
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Headers/__stddef_unreachable.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
*===-----------------------------------------------------------------------===
*/

#ifndef __cplusplus

/*
* When -fbuiltin-headers-in-system-modules is set this is a non-modular header
* and needs to behave as if it was textual.
Expand All @@ -15,3 +17,5 @@
(__has_feature(modules) && !__building_module(_Builtin_stddef))
#define unreachable() __builtin_unreachable()
#endif

#endif
112 changes: 112 additions & 0 deletions clang/lib/Headers/hlsl/hlsl_intrinsics.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,118 @@ double3 abs(double3);
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_abs)
double4 abs(double4);

//===----------------------------------------------------------------------===//
// all builtins
//===----------------------------------------------------------------------===//

/// \fn bool all(T x)
/// \brief Returns True if all components of the \a x parameter are non-zero;
/// otherwise, false. \param x The input value.

#ifdef __HLSL_ENABLE_16_BIT
_HLSL_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(int16_t);
_HLSL_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(int16_t2);
_HLSL_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(int16_t3);
_HLSL_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(int16_t4);
_HLSL_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(uint16_t);
_HLSL_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(uint16_t2);
_HLSL_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(uint16_t3);
_HLSL_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(uint16_t4);
#endif

_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(half);
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(half2);
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(half3);
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(half4);

_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(bool);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(bool2);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(bool3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(bool4);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)

_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(int);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(int2);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(int3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(int4);

_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(uint);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(uint2);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(uint3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(uint4);

_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(float);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(float2);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(float3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(float4);

_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(int64_t);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(int64_t2);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(int64_t3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(int64_t4);

_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(uint64_t);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(uint64_t2);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(uint64_t3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(uint64_t4);

_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(double);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(double2);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(double3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
bool all(double4);

//===----------------------------------------------------------------------===//
// any builtins
//===----------------------------------------------------------------------===//
Expand Down
8 changes: 4 additions & 4 deletions clang/lib/InstallAPI/Visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,10 +205,10 @@ bool InstallAPIVisitor::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
const ObjCInterfaceDecl *InterfaceD = D->getClassInterface();
const StringRef InterfaceName = InterfaceD->getName();

std::pair<ObjCCategoryRecord *, FrontendAttrs *> Category =
Ctx.Slice->addObjCCategory(InterfaceName, CategoryName, Avail, D,
*Access);
recordObjCInstanceVariables(D->getASTContext(), Category.first, InterfaceName,
ObjCCategoryRecord *CategoryRecord =
Ctx.Slice->addObjCCategory(InterfaceName, CategoryName, Avail, D, *Access)
.first;
recordObjCInstanceVariables(D->getASTContext(), CategoryRecord, InterfaceName,
D->ivars());
return true;
}
Expand Down
33 changes: 24 additions & 9 deletions clang/lib/Parse/ParseDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1502,6 +1502,15 @@ void Parser::ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs) {
}
}

void Parser::ParseNullabilityClassAttributes(ParsedAttributes &attrs) {
while (Tok.is(tok::kw__Nullable)) {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
auto Kind = Tok.getKind();
SourceLocation AttrNameLoc = ConsumeToken();
attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, Kind);
}
}

/// Determine whether the following tokens are valid after a type-specifier
/// which could be a standalone declaration. This will conservatively return
/// true if there's any doubt, and is appropriate for insert-';' fixits.
Expand Down Expand Up @@ -1683,15 +1692,21 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,

ParsedAttributes attrs(AttrFactory);
// If attributes exist after tag, parse them.
MaybeParseAttributes(PAKM_CXX11 | PAKM_Declspec | PAKM_GNU, attrs);

// Parse inheritance specifiers.
if (Tok.isOneOf(tok::kw___single_inheritance, tok::kw___multiple_inheritance,
tok::kw___virtual_inheritance))
ParseMicrosoftInheritanceClassAttributes(attrs);

// Allow attributes to precede or succeed the inheritance specifiers.
MaybeParseAttributes(PAKM_CXX11 | PAKM_Declspec | PAKM_GNU, attrs);
for (;;) {
MaybeParseAttributes(PAKM_CXX11 | PAKM_Declspec | PAKM_GNU, attrs);
// Parse inheritance specifiers.
if (Tok.isOneOf(tok::kw___single_inheritance,
tok::kw___multiple_inheritance,
tok::kw___virtual_inheritance)) {
ParseMicrosoftInheritanceClassAttributes(attrs);
continue;
}
if (Tok.is(tok::kw__Nullable)) {
ParseNullabilityClassAttributes(attrs);
continue;
}
break;
}

// Source location used by FIXIT to insert misplaced
// C++11 attributes
Expand Down
21 changes: 11 additions & 10 deletions clang/lib/Parse/ParseOpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/SemaOpenACC.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"

Expand Down Expand Up @@ -777,7 +778,7 @@ bool Parser::ParseOpenACCClause(OpenACCDirectiveKind DirKind) {
SourceLocation ClauseLoc = ConsumeToken();

bool Result = ParseOpenACCClauseParams(DirKind, Kind);
getActions().ActOnOpenACCClause(Kind, ClauseLoc);
getActions().OpenACC().ActOnClause(Kind, ClauseLoc);
return Result;
}

Expand Down Expand Up @@ -1151,7 +1152,7 @@ Parser::OpenACCDirectiveParseInfo Parser::ParseOpenACCDirective() {
SourceLocation StartLoc = getCurToken().getLocation();
OpenACCDirectiveKind DirKind = ParseOpenACCDirectiveKind(*this);

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

// Once we've parsed the construct/directive name, some have additional
// specifiers that need to be taken care of. Atomic has an 'atomic-clause'
Expand Down Expand Up @@ -1223,12 +1224,12 @@ Parser::DeclGroupPtrTy Parser::ParseOpenACCDirectiveDecl() {

OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective();

if (getActions().ActOnStartOpenACCDeclDirective(DirInfo.DirKind,
DirInfo.StartLoc))
if (getActions().OpenACC().ActOnStartDeclDirective(DirInfo.DirKind,
DirInfo.StartLoc))
return nullptr;

// TODO OpenACC: Do whatever decl parsing is required here.
return DeclGroupPtrTy::make(getActions().ActOnEndOpenACCDeclDirective());
return DeclGroupPtrTy::make(getActions().OpenACC().ActOnEndDeclDirective());
}

// Parse OpenACC Directive on a Statement.
Expand All @@ -1239,8 +1240,8 @@ StmtResult Parser::ParseOpenACCDirectiveStmt() {
ConsumeAnnotationToken();

OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective();
if (getActions().ActOnStartOpenACCStmtDirective(DirInfo.DirKind,
DirInfo.StartLoc))
if (getActions().OpenACC().ActOnStartStmtDirective(DirInfo.DirKind,
DirInfo.StartLoc))
return StmtError();

StmtResult AssocStmt;
Expand All @@ -1249,10 +1250,10 @@ StmtResult Parser::ParseOpenACCDirectiveStmt() {
ParsingOpenACCDirectiveRAII DirScope(*this, /*Value=*/false);
ParseScope ACCScope(this, getOpenACCScopeFlags(DirInfo.DirKind));

AssocStmt = getActions().ActOnOpenACCAssociatedStmt(DirInfo.DirKind,
ParseStatement());
AssocStmt = getActions().OpenACC().ActOnAssociatedStmt(DirInfo.DirKind,
ParseStatement());
}

return getActions().ActOnEndOpenACCStmtDirective(
return getActions().OpenACC().ActOnEndStmtDirective(
DirInfo.DirKind, DirInfo.StartLoc, DirInfo.EndLoc, AssocStmt);
}
1 change: 1 addition & 0 deletions clang/lib/Sema/JumpDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtOpenACC.h"
#include "clang/AST/StmtOpenMP.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Sema/SemaInternal.h"
Expand Down
Loading