Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 3 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,8 @@ Improvements to Clang's diagnostics
that were previously incorrectly accepted in case of other irrelevant
conditions are now consistently diagnosed, identical to C++ mode.

- Fix false-positive unused label diagnostic when a label is used in a named break
or continue (#GH166013)
- Clang now emits a diagnostic in case `vector_size` or `ext_vector_type`
attributes are used with a negative size (#GH165463).

Expand Down Expand Up @@ -753,6 +755,7 @@ Bug Fixes to C++ Support
nontrivial member when another member has an initializer. (#GH81774)
- Fixed a template depth issue when parsing lambdas inside a type constraint. (#GH162092)
- Diagnose unresolved overload sets in non-dependent compound requirements. (#GH51246) (#GH97753)
- Fix a crash when extracting unavailable member type from alias in template deduction. (#GH165560)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Sema/SemaStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3281,6 +3281,9 @@ static Scope *FindLabeledBreakContinueScope(Sema &S, Scope *CurScope,
SourceLocation LabelLoc,
bool IsContinue) {
assert(Target && "not a named break/continue?");

Target->markUsed(S.Context);

Scope *Found = nullptr;
for (Scope *Scope = CurScope; Scope; Scope = Scope->getParent()) {
if (Scope->isFunctionScope())
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Sema/SemaTemplateDeductionGuide.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,8 @@ struct ConvertConstructorToDeductionGuideTransform {
SemaRef, MaterializedTypedefs, NestedPattern,
TransformingOuterPatterns ? &Args : nullptr)
.transform(NewDI);

if (!NewDI)
return nullptr;
// Resolving a wording defect, we also inherit default arguments from the
// constructor.
ExprResult NewDefArg;
Expand Down
3 changes: 1 addition & 2 deletions clang/lib/Serialization/ASTWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4374,8 +4374,7 @@ class ASTDeclContextNameLookupTrait
// parent of parent. We DON'T remove the enum constant from its parent. So
// we don't need to care about merging problems here.
if (auto *ECD = dyn_cast<EnumConstantDecl>(D);
ECD && DC.isFileContext() && ECD->getOwningModule() &&
ECD->getTopLevelOwningNamedModule()->isNamedModule()) {
ECD && DC.isFileContext() && ECD->getTopLevelOwningNamedModule()) {
if (llvm::all_of(
DC.noload_lookup(
cast<EnumDecl>(ECD->getDeclContext())->getDeclName()),
Expand Down
46 changes: 46 additions & 0 deletions clang/test/Modules/crash-enum-visibility-with-header-unit.cppm
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Fixes #165445

// RUN: rm -rf %t
// RUN: mkdir -p %t
// RUN: split-file %s %t
//
// RUN: %clang_cc1 -std=c++20 -x c++-user-header %t/header.h \
// RUN: -emit-header-unit -o %t/header.pcm
//
// RUN: %clang_cc1 -std=c++20 %t/A.cppm -fmodule-file=%t/header.pcm \
// RUN: -emit-module-interface -o %t/A.pcm
//
// RUN: %clang_cc1 -std=c++20 %t/B.cppm -fmodule-file=%t/header.pcm \
// RUN: -emit-module-interface -o %t/B.pcm
//
// RUN: %clang_cc1 -std=c++20 %t/use.cpp \
// RUN: -fmodule-file=A=%t/A.pcm -fmodule-file=B=%t/B.pcm \
// RUN: -fmodule-file=%t/header.pcm \
// RUN: -verify -fsyntax-only

//--- enum.h
enum E { Value };

//--- header.h
#include "enum.h"

//--- A.cppm
module;
#include "enum.h"
export module A;

auto e = Value;

//--- B.cppm
export module B;
import "header.h";

auto e = Value;

//--- use.cpp
// expected-no-diagnostics
import A;
import B;
#include "enum.h"

auto e = Value;
18 changes: 15 additions & 3 deletions clang/test/Sema/labeled-break-continue.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -std=c2y -verify -fsyntax-only -fblocks %s
// RUN: %clang_cc1 -std=c23 -verify -fsyntax-only -fblocks -fnamed-loops %s
// RUN: %clang_cc1 -x c++ -verify -fsyntax-only -fblocks -fnamed-loops %s
// RUN: %clang_cc1 -std=c2y -verify -Wunused -fsyntax-only -fblocks %s
// RUN: %clang_cc1 -std=c23 -verify -Wunused -fsyntax-only -fblocks -fnamed-loops %s
// RUN: %clang_cc1 -x c++ -verify -Wunused -fsyntax-only -fblocks -fnamed-loops %s

void f1() {
l1: while (true) {
Expand Down Expand Up @@ -159,3 +159,15 @@ void f7() {
continue d; // expected-error {{'continue' label does not name an enclosing loop}}
}
}

void f8() {
l1: // no-warning
while (true) {
break l1;
}

l2: // no-warning
while (true) {
continue l2;
}
}
12 changes: 12 additions & 0 deletions clang/test/SemaTemplate/ctad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,15 @@ namespace ConvertDeducedTemplateArgument {

auto x = C(D<A::B>());
}

namespace pr165560 {
template <class T, class> struct S {
using A = T;
template <class> struct I { // expected-note{{candidate function template not viable: requires 1 argument, but 0 were provided}} \
// expected-note{{implicit deduction guide declared as 'template <class> I(pr165560::S<int, int>::I<type-parameter-0-0>) -> pr165560::S<int, int>::I<type-parameter-0-0>'}}
I(typename A::F) {} // expected-error{{type 'A' (aka 'int') cannot be used prior to '::' because it has no members}}
};
};
S<int, int>::I i; // expected-error{{no viable constructor or deduction guide for deduction of template arguments of 'S<int, int>::I'}} \
// expected-note{{while building implicit deduction guide first needed here}}
}
2 changes: 2 additions & 0 deletions lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,8 @@ bool ABISysV_riscv::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
.Cases({"f8", "f9", "f18", "f19", "f20", "f21", "f22", "f23"},
is_hw_fp)
.Cases({"f24", "f25", "f26", "f27"}, is_hw_fp)
// vlenb is constant and needed for vector unwinding.
.Case("vlenb", true)
.Default(false);

return is_callee_saved;
Expand Down
6 changes: 6 additions & 0 deletions llvm/docs/RISCVUsage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,12 @@ The current vendor extensions supported are:
``XSfvcp``
LLVM implements `version 1.1.0 of the SiFive Vector Coprocessor Interface (VCIX) Software Specification <https://sifive.cdn.prismic.io/sifive/Zn3m1R5LeNNTwnLS_vcix-spec-software-v1p1.pdf>`__ by SiFive. All instructions are prefixed with `sf.vc.` as described in the specification, and the riscv-toolchain-convention document linked above.

``Xsfvfexp16e``, ``Xsfvfbfexp16e``, and ``Xsfvfexp32e``
LLVM implements `version 0.5 of the Vector Exponential Extension Specification <https://www.sifive.com/document-file/exponential-function-instruction-xsfvfexp32e-xsfvf>`__ by SiFive. All instructions are prefixed with `sf.` as described in the specification linked above.

``Xsfvfexpa`` and ``Xsfvfexpa64e``
LLVM implements `version 0.2 of the Vector Exponential Approximation Extension Specification <https://www.sifive.com/document-file/exponential-approximation-instruction-xsfvfexpa-ex>`__ by SiFive. All instructions are prefixed with `sf.` as described in the specification linked above.

``XSfvqmaccdod``, ``XSfvqmaccqoq``
LLVM implements `version 1.1.0 of the SiFive Int8 Matrix Multiplication Extensions Specification <https://sifive.cdn.prismic.io/sifive/1a2ad85b-d818-49f7-ba83-f51f1731edbe_int8-matmul-spec.pdf>`__ by SiFive. All instructions are prefixed with `sf.` as described in the specification linked above.

Expand Down
125 changes: 121 additions & 4 deletions llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ class RISCVInstructionSelector : public InstructionSelector {
void addVectorLoadStoreOperands(MachineInstr &I,
SmallVectorImpl<SrcOp> &SrcOps,
unsigned &CurOp, bool IsMasked,
bool IsStrided) const;
bool IsStridedOrIndexed,
LLT *IndexVT = nullptr) const;
bool selectIntrinsicWithSideEffects(MachineInstr &I,
MachineIRBuilder &MIB) const;

Expand Down Expand Up @@ -722,15 +723,17 @@ static unsigned selectRegImmLoadStoreOp(unsigned GenericOpc, unsigned OpSize) {

void RISCVInstructionSelector::addVectorLoadStoreOperands(
MachineInstr &I, SmallVectorImpl<SrcOp> &SrcOps, unsigned &CurOp,
bool IsMasked, bool IsStrided) const {
bool IsMasked, bool IsStridedOrIndexed, LLT *IndexVT) const {
// Base Pointer
auto PtrReg = I.getOperand(CurOp++).getReg();
SrcOps.push_back(PtrReg);

// Stride
if (IsStrided) {
// Stride or Index
if (IsStridedOrIndexed) {
auto StrideReg = I.getOperand(CurOp++).getReg();
SrcOps.push_back(StrideReg);
if (IndexVT)
*IndexVT = MRI->getType(StrideReg);
}

// Mask
Expand Down Expand Up @@ -805,6 +808,70 @@ bool RISCVInstructionSelector::selectIntrinsicWithSideEffects(
I.eraseFromParent();
return constrainSelectedInstRegOperands(*PseudoMI, TII, TRI, RBI);
}
case Intrinsic::riscv_vloxei:
case Intrinsic::riscv_vloxei_mask:
case Intrinsic::riscv_vluxei:
case Intrinsic::riscv_vluxei_mask: {
bool IsMasked = IntrinID == Intrinsic::riscv_vloxei_mask ||
IntrinID == Intrinsic::riscv_vluxei_mask;
bool IsOrdered = IntrinID == Intrinsic::riscv_vloxei ||
IntrinID == Intrinsic::riscv_vloxei_mask;
LLT VT = MRI->getType(I.getOperand(0).getReg());
unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());

// Result vector
const Register DstReg = I.getOperand(0).getReg();

// Sources
bool HasPassthruOperand = IntrinID != Intrinsic::riscv_vlm;
unsigned CurOp = 2;
SmallVector<SrcOp, 4> SrcOps; // Source registers.

// Passthru
if (HasPassthruOperand) {
auto PassthruReg = I.getOperand(CurOp++).getReg();
SrcOps.push_back(PassthruReg);
} else {
// Use NoRegister if there is no specified passthru.
SrcOps.push_back(Register());
}
LLT IndexVT;
addVectorLoadStoreOperands(I, SrcOps, CurOp, IsMasked, true, &IndexVT);

RISCVVType::VLMUL LMUL = RISCVTargetLowering::getLMUL(getMVTForLLT(VT));
RISCVVType::VLMUL IndexLMUL =
RISCVTargetLowering::getLMUL(getMVTForLLT(IndexVT));
unsigned IndexLog2EEW = Log2_32(IndexVT.getScalarSizeInBits());
if (IndexLog2EEW == 6 && !Subtarget->is64Bit()) {
reportFatalUsageError("The V extension does not support EEW=64 for index "
"values when XLEN=32");
}
const RISCV::VLX_VSXPseudo *P = RISCV::getVLXPseudo(
IsMasked, IsOrdered, IndexLog2EEW, static_cast<unsigned>(LMUL),
static_cast<unsigned>(IndexLMUL));

auto PseudoMI = MIB.buildInstr(P->Pseudo, {DstReg}, SrcOps);

// Select VL
auto VLOpFn = renderVLOp(I.getOperand(CurOp++));
for (auto &RenderFn : *VLOpFn)
RenderFn(PseudoMI);

// SEW
PseudoMI.addImm(Log2SEW);

// Policy
uint64_t Policy = RISCVVType::MASK_AGNOSTIC;
if (IsMasked)
Policy = I.getOperand(CurOp++).getImm();
PseudoMI.addImm(Policy);

// Memref
PseudoMI.cloneMemRefs(I);

I.eraseFromParent();
return constrainSelectedInstRegOperands(*PseudoMI, TII, TRI, RBI);
}
case Intrinsic::riscv_vsm:
case Intrinsic::riscv_vse:
case Intrinsic::riscv_vse_mask:
Expand Down Expand Up @@ -847,6 +914,56 @@ bool RISCVInstructionSelector::selectIntrinsicWithSideEffects(
I.eraseFromParent();
return constrainSelectedInstRegOperands(*PseudoMI, TII, TRI, RBI);
}
case Intrinsic::riscv_vsoxei:
case Intrinsic::riscv_vsoxei_mask:
case Intrinsic::riscv_vsuxei:
case Intrinsic::riscv_vsuxei_mask: {
bool IsMasked = IntrinID == Intrinsic::riscv_vsoxei_mask ||
IntrinID == Intrinsic::riscv_vsuxei_mask;
bool IsOrdered = IntrinID == Intrinsic::riscv_vsoxei ||
IntrinID == Intrinsic::riscv_vsoxei_mask;
LLT VT = MRI->getType(I.getOperand(1).getReg());
unsigned Log2SEW = Log2_32(VT.getScalarSizeInBits());

// Sources
unsigned CurOp = 1;
SmallVector<SrcOp, 4> SrcOps; // Source registers.

// Store value
auto PassthruReg = I.getOperand(CurOp++).getReg();
SrcOps.push_back(PassthruReg);

LLT IndexVT;
addVectorLoadStoreOperands(I, SrcOps, CurOp, IsMasked, true, &IndexVT);

RISCVVType::VLMUL LMUL = RISCVTargetLowering::getLMUL(getMVTForLLT(VT));
RISCVVType::VLMUL IndexLMUL =
RISCVTargetLowering::getLMUL(getMVTForLLT(IndexVT));
unsigned IndexLog2EEW = Log2_32(IndexVT.getScalarSizeInBits());
if (IndexLog2EEW == 6 && !Subtarget->is64Bit()) {
reportFatalUsageError("The V extension does not support EEW=64 for index "
"values when XLEN=32");
}
const RISCV::VLX_VSXPseudo *P = RISCV::getVSXPseudo(
IsMasked, IsOrdered, IndexLog2EEW, static_cast<unsigned>(LMUL),
static_cast<unsigned>(IndexLMUL));

auto PseudoMI = MIB.buildInstr(P->Pseudo, {}, SrcOps);

// Select VL
auto VLOpFn = renderVLOp(I.getOperand(CurOp++));
for (auto &RenderFn : *VLOpFn)
RenderFn(PseudoMI);

// SEW
PseudoMI.addImm(Log2SEW);

// Memref
PseudoMI.cloneMemRefs(I);

I.eraseFromParent();
return constrainSelectedInstRegOperands(*PseudoMI, TII, TRI, RBI);
}
}
}

Expand Down
Loading