Skip to content

Commit 60be059

Browse files
SC llvm teamSC llvm team
SC llvm team
authored and
SC llvm team
committed
Merged main:2d4de5acfa2a into amd-gfx:f79988bb6fb8
Local branch amd-gfx f79988b Merged main:f756061387c8 into amd-gfx:63e627b07a2b Remote branch main 2d4de5a [clang][Interp] Implement IntegralAP::comp (llvm#67954)
2 parents f79988b + 2d4de5a commit 60be059

File tree

80 files changed

+934
-496
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

80 files changed

+934
-496
lines changed

.ci/generate-buildkite-pipeline-premerge

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ set -o pipefail
2222

2323
# Environment variables script works with:
2424
# List of files affected by this commit
25-
: ${MODIFIED_FILES:=$(git diff --name-only main...HEAD)}
25+
: ${MODIFIED_FILES:=$(git diff --name-only HEAD~1)}
2626
# Filter rules for generic windows tests
2727
: ${WINDOWS_AGENTS:='{"queue": "windows"}'}
2828
# Filter rules for generic linux tests

clang/docs/ReleaseNotes.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,10 @@ Bug Fixes to C++ Support
383383
- Fixed a bug causing destructors of constant-evaluated structured bindings
384384
initialized by array elements to be called in the wrong evaluation context.
385385

386+
- Fix crash where ill-formed code was being treated as a deduction guide and
387+
we now produce a diagnostic. Fixes:
388+
(`#65522 <https://github.com/llvm/llvm-project/issues/65522>`_)
389+
386390
Bug Fixes to AST Handling
387391
^^^^^^^^^^^^^^^^^^^^^^^^^
388392
- Fixed an import failure of recursive friend class template.
@@ -538,6 +542,14 @@ Static Analyzer
538542
Read the PR for the details.
539543
(`#66086 <https://github.com/llvm/llvm-project/pull/66086>`_)
540544

545+
- A few crashes have been found and fixed using randomized testing related
546+
to the use of ``_BitInt()`` in tidy checks and in clang analysis. See
547+
`#67212 <https://github.com/llvm/llvm-project/pull/67212>`_,
548+
`#66782 <https://github.com/llvm/llvm-project/pull/66782>`_,
549+
`#65889 <https://github.com/llvm/llvm-project/pull/65889>`_,
550+
`#65888 <https://github.com/llvm/llvm-project/pull/65888>`_, and
551+
`#65887 <https://github.com/llvm/llvm-project/pull/65887>`_
552+
541553
.. _release-notes-sanitizers:
542554

543555
Sanitizers

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5416,6 +5416,8 @@ def note_constraint_normalization_here : Note<
54165416
def note_parameter_mapping_substitution_here : Note<
54175417
"while substituting into concept arguments here; substitution failures not "
54185418
"allowed in concept arguments">;
5419+
def note_building_deduction_guide_here : Note<
5420+
"while building implicit deduction guide first needed here">;
54195421
def note_lambda_substitution_here : Note<
54205422
"while substituting into a lambda expression here">;
54215423
def note_instantiation_contexts_suppressed : Note<

clang/lib/AST/Interp/IntegralAP.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,6 @@ template <bool Signed> class IntegralAP final {
210210
}
211211

212212
static bool comp(IntegralAP A, IntegralAP *R) {
213-
assert(false);
214213
*R = IntegralAP(~A.V);
215214
return false;
216215
}

clang/lib/AST/Interp/InterpBuiltin.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,16 @@ static bool interp__builtin_fabs(InterpState &S, CodePtr OpPC,
398398
return true;
399399
}
400400

401+
static bool interp__builtin_popcount(InterpState &S, CodePtr OpPC,
402+
const InterpFrame *Frame,
403+
const Function *Func,
404+
const CallExpr *Call) {
405+
PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
406+
APSInt Val = peekToAPSInt(S.Stk, ArgT);
407+
pushInt(S, Val.popcount());
408+
return true;
409+
}
410+
401411
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
402412
const CallExpr *Call) {
403413
InterpFrame *Frame = S.Current;
@@ -513,6 +523,16 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
513523
return Ret<PT_Float>(S, OpPC, Dummy);
514524
break;
515525

526+
case Builtin::BI__builtin_popcount:
527+
case Builtin::BI__builtin_popcountl:
528+
case Builtin::BI__builtin_popcountll:
529+
case Builtin::BI__popcnt16: // Microsoft variants of popcount
530+
case Builtin::BI__popcnt:
531+
case Builtin::BI__popcnt64:
532+
if (interp__builtin_popcount(S, OpPC, Frame, F, Call))
533+
return retInt(S, OpPC, Dummy);
534+
break;
535+
516536
default:
517537
return false;
518538
}

clang/lib/AST/Interp/Source.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@
1414
#define LLVM_CLANG_AST_INTERP_SOURCE_H
1515

1616
#include "PrimType.h"
17+
#include "clang/AST/DeclBase.h"
18+
#include "clang/AST/Stmt.h"
1719
#include "llvm/ADT/PointerUnion.h"
1820
#include "llvm/Support/Endian.h"
1921

2022
namespace clang {
21-
class Stmt;
22-
class Decl;
2323
class Expr;
2424
class SourceLocation;
2525
class SourceRange;

clang/lib/Sema/SemaTemplateInstantiate.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1075,7 +1075,9 @@ void Sema::PrintInstantiationStack() {
10751075
<< Active->InstantiationRange;
10761076
break;
10771077
case CodeSynthesisContext::BuildingDeductionGuides:
1078-
llvm_unreachable("unexpected deduction guide in instantiation stack");
1078+
Diags.Report(Active->PointOfInstantiation,
1079+
diag::note_building_deduction_guide_here);
1080+
break;
10791081
}
10801082
}
10811083
}

clang/lib/StaticAnalyzer/Core/BasicValueFactory.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ BasicValueFactory::evalAPSInt(BinaryOperator::Opcode Op,
272272
// FIXME: This logic should probably go higher up, where we can
273273
// test these conditions symbolically.
274274

275-
if (V2.isSigned() && V2.isNegative())
275+
if (V2.isNegative() || V2.getBitWidth() > 64)
276276
return nullptr;
277277

278278
uint64_t Amt = V2.getZExtValue();
@@ -287,7 +287,7 @@ BasicValueFactory::evalAPSInt(BinaryOperator::Opcode Op,
287287
// FIXME: This logic should probably go higher up, where we can
288288
// test these conditions symbolically.
289289

290-
if (V2.isSigned() && V2.isNegative())
290+
if (V2.isNegative() || V2.getBitWidth() > 64)
291291
return nullptr;
292292

293293
uint64_t Amt = V2.getZExtValue();

clang/test/AST/Interp/builtin-functions.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,3 +260,25 @@ namespace SourceLocation {
260260
static_assert(c.a.n == __LINE__ - 1, "");
261261
}
262262
}
263+
264+
namespace popcount {
265+
static_assert(__builtin_popcount(~0u) == __CHAR_BIT__ * sizeof(unsigned int), "");
266+
static_assert(__builtin_popcount(0) == 0, "");
267+
static_assert(__builtin_popcountl(~0ul) == __CHAR_BIT__ * sizeof(unsigned long), "");
268+
static_assert(__builtin_popcountl(0) == 0, "");
269+
static_assert(__builtin_popcountll(~0ull) == __CHAR_BIT__ * sizeof(unsigned long long), "");
270+
static_assert(__builtin_popcountll(0) == 0, "");
271+
272+
/// From test/Sema/constant-builtins-2.c
273+
#define BITSIZE(x) (sizeof(x) * 8)
274+
char popcount1[__builtin_popcount(0) == 0 ? 1 : -1];
275+
char popcount2[__builtin_popcount(0xF0F0) == 8 ? 1 : -1];
276+
char popcount3[__builtin_popcount(~0) == BITSIZE(int) ? 1 : -1];
277+
char popcount4[__builtin_popcount(~0L) == BITSIZE(int) ? 1 : -1];
278+
char popcount5[__builtin_popcountl(0L) == 0 ? 1 : -1];
279+
char popcount6[__builtin_popcountl(0xF0F0L) == 8 ? 1 : -1];
280+
char popcount7[__builtin_popcountl(~0L) == BITSIZE(long) ? 1 : -1];
281+
char popcount8[__builtin_popcountll(0LL) == 0 ? 1 : -1];
282+
char popcount9[__builtin_popcountll(0xF0F0LL) == 8 ? 1 : -1];
283+
char popcount10[__builtin_popcountll(~0LL) == BITSIZE(long long) ? 1 : -1];
284+
}

clang/test/AST/Interp/literals.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ namespace i128 {
5252
constexpr int128_t Two = (int128_t)1 << 1ul;
5353
static_assert(Two == 2, "");
5454

55+
constexpr uint128_t AllOnes = ~static_cast<uint128_t>(0);
56+
static_assert(AllOnes == static_cast<uint128_t>(-1), "");
57+
5558
#if __cplusplus >= 201402L
5659
template <typename T>
5760
constexpr T CastFrom(__int128_t A) {

clang/test/Analysis/int128-nocrash.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %clang_analyze_cc1 -analyzer-checker=optin.portability.UnixAPI \
2+
// RUN: -triple x86_64-pc-linux-gnu -x c %s
3+
4+
// Don't crash!
5+
// expected-no-diagnostics
6+
const __int128_t a = ( (__int128_t)1 << 64 );
7+
const _BitInt(72) b = ( 1 << 72 );
8+
9+
void int128() {
10+
2 >> a;
11+
}
12+
13+
void withbitint() {
14+
2 >> b;
15+
}

clang/test/CXX/drs/dr12xx.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ namespace dr1213 { // dr1213: 7
3232
}
3333

3434
#if __cplusplus >= 201103L
35-
namespace dr1223 { // dr1227: yes open
35+
namespace dr1223 { // dr1223: 17 drafting
3636
struct M;
3737
template <typename T>
3838
struct V;

clang/test/CXX/drs/dr13xx.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,23 @@ namespace dr1330 { // dr1330: 4 c++11
254254
#endif
255255
}
256256

257+
namespace dr1341 { // dr1341: sup P0683R1
258+
#if __cplusplus >= 202002L
259+
int a;
260+
const int b = 0; // #dr1341-b-decl
261+
struct S {
262+
int x1 : 8 = 42;
263+
int x2 : 8 { 42 };
264+
int y1 : true ? 8 : a = 42;
265+
int y2 : true ? 8 : b = 42;
266+
// expected-error@-1 {{cannot assign to variable 'b' with const-qualified type 'const int'}}
267+
// expected-note@#dr1341-b-decl {{variable 'b' declared const here}}
268+
int y3 : (true ? 8 : b) = 42;
269+
int z : 1 || new int { 0 };
270+
};
271+
#endif
272+
}
273+
257274
namespace dr1346 { // dr1346: 3.5
258275
auto a(1); // expected-error 0-1{{extension}}
259276
auto b(1, 2); // expected-error {{multiple expressions}} expected-error 0-1{{extension}}

clang/test/SemaCXX/gh65522.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %clang_cc1 -std=c++20 -Wc++17-compat -verify -Wno-unused %s
2+
3+
class X {};
4+
5+
template<typename T>
6+
class B3 { // expected-note {{candidate template ignored: could not match 'B3<T>' against 'int'}}
7+
template<X x> B3(T); // expected-warning 2{{non-type template parameter of type 'X' is incompatible with C++ standards before C++20}} \
8+
// expected-note {{candidate template ignored: couldn't infer template argument 'x'}}
9+
};
10+
B3 b3 = 0; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'B3'}} \
11+
// expected-note {{while building implicit deduction guide first needed here}}

clang/www/cxx_dr_status.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7145,7 +7145,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
71457145
<td><a href="https://cplusplus.github.io/CWG/issues/1223.html">1223</a></td>
71467146
<td>drafting</td>
71477147
<td>Syntactic disambiguation and <I>trailing-return-type</I>s</td>
7148-
<td align="center">Not resolved</td>
7148+
<td class="unreleased" align="center">Clang 17</td>
71497149
</tr>
71507150
<tr id="1224">
71517151
<td><a href="https://cplusplus.github.io/CWG/issues/1224.html">1224</a></td>
@@ -7853,7 +7853,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
78537853
<td><a href="https://cplusplus.github.io/CWG/issues/1341.html">1341</a></td>
78547854
<td>NAD</td>
78557855
<td>Bit-field initializers</td>
7856-
<td class="none" align="center">Unknown</td>
7856+
<td class="na" align="center">Superseded by <a href="https://wg21.link/P0683R1">P0683R1</a></td>
78577857
</tr>
78587858
<tr id="1342">
78597859
<td><a href="https://cplusplus.github.io/CWG/issues/1342.html">1342</a></td>

clang/www/make_cxx_dr_status

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,11 @@ def collect_tests():
3939
test_cpp = os.path.join(dr_test_dir, test_cpp)
4040
found_any = False;
4141
for match in re.finditer(status_re, open(test_cpp, 'r').read()):
42-
status_map[int(match.group(1))] = match.group(2)
42+
dr_number = int(match.group(1))
43+
if dr_number in status_map:
44+
print("error: Comment for dr{} encountered more than once. Duplicate found in {}".format(dr_number, test_cpp))
45+
sys.exit(1)
46+
status_map[dr_number] = match.group(2)
4347
found_any = True
4448
if not found_any:
4549
print("warning:%s: no '// dr123: foo' comments in this file" % test_cpp, file=sys.stderr)

flang/lib/Lower/ConvertCall.cpp

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -428,14 +428,36 @@ fir::ExtendedValue Fortran::lower::genCallOpAndResult(
428428
}
429429

430430
if (allocatedResult) {
431+
// The result must be optionally destroyed (if it is of a derived type
432+
// that may need finalization or deallocation of the components).
433+
// For an allocatable result we have to free the memory allocated
434+
// for the top-level entity. Note that the Destroy calls below
435+
// do not deallocate the top-level entity. The two clean-ups
436+
// must be pushed in reverse order, so that the final order is:
437+
// Destroy(desc)
438+
// free(desc->base_addr)
439+
allocatedResult->match(
440+
[&](const fir::MutableBoxValue &box) {
441+
if (box.isAllocatable()) {
442+
// 9.7.3.2 point 4. Deallocate allocatable results. Note that
443+
// finalization was done independently by calling
444+
// genDerivedTypeDestroy above and is not triggered by this inline
445+
// deallocation.
446+
fir::FirOpBuilder *bldr = &converter.getFirOpBuilder();
447+
stmtCtx.attachCleanup([bldr, loc, box]() {
448+
fir::factory::genFreememIfAllocated(*bldr, loc, box);
449+
});
450+
}
451+
},
452+
[](const auto &) {});
453+
431454
// 7.5.6.3 point 5. Derived-type finalization for nonpointer function.
432455
// Check if the derived-type is finalizable if it is a monomorphic
433456
// derived-type.
434457
// For polymorphic and unlimited polymorphic enities call the runtime
435458
// in any cases.
436459
std::optional<Fortran::evaluate::DynamicType> retTy =
437460
caller.getCallDescription().proc().GetType();
438-
bool cleanupWithDestroy = false;
439461
// With HLFIR lowering, isElemental must be set to true
440462
// if we are producing an elemental call. In this case,
441463
// the elemental results must not be destroyed, instead,
@@ -451,34 +473,23 @@ fir::ExtendedValue Fortran::lower::genCallOpAndResult(
451473
fir::runtime::genDerivedTypeDestroy(*bldr, loc,
452474
fir::getBase(*allocatedResult));
453475
});
454-
cleanupWithDestroy = true;
455476
} else {
456477
const Fortran::semantics::DerivedTypeSpec &typeSpec =
457478
retTy->GetDerivedTypeSpec();
458-
if (Fortran::semantics::IsFinalizable(typeSpec)) {
479+
// If the result type may require finalization
480+
// or have allocatable components, we need to make sure
481+
// everything is properly finalized/deallocated.
482+
if (Fortran::semantics::MayRequireFinalization(typeSpec) ||
483+
// We can use DerivedTypeDestroy even if finalization is not needed.
484+
hlfir::mayHaveAllocatableComponent(funcType.getResults()[0])) {
459485
auto *bldr = &converter.getFirOpBuilder();
460486
stmtCtx.attachCleanup([bldr, loc, allocatedResult]() {
461487
mlir::Value box = bldr->createBox(loc, *allocatedResult);
462488
fir::runtime::genDerivedTypeDestroy(*bldr, loc, box);
463489
});
464-
cleanupWithDestroy = true;
465490
}
466491
}
467492
}
468-
allocatedResult->match(
469-
[&](const fir::MutableBoxValue &box) {
470-
if (box.isAllocatable() && !cleanupWithDestroy) {
471-
// 9.7.3.2 point 4. Deallocate allocatable results. Note that
472-
// finalization was done independently by calling
473-
// genDerivedTypeDestroy above and is not triggered by this inline
474-
// deallocation.
475-
fir::FirOpBuilder *bldr = &converter.getFirOpBuilder();
476-
stmtCtx.attachCleanup([bldr, loc, box]() {
477-
fir::factory::genFreememIfAllocated(*bldr, loc, box);
478-
});
479-
}
480-
},
481-
[](const auto &) {});
482493
return *allocatedResult;
483494
}
484495

@@ -1232,8 +1243,25 @@ genUserCall(Fortran::lower::PreparedActualArguments &loweredActuals,
12321243

12331244
if (!fir::getBase(result))
12341245
return std::nullopt; // subroutine call.
1235-
// TODO: "move" non pointer results into hlfir.expr.
1236-
return extendedValueToHlfirEntity(loc, builder, result, ".tmp.func_result");
1246+
1247+
hlfir::Entity resultEntity =
1248+
extendedValueToHlfirEntity(loc, builder, result, ".tmp.func_result");
1249+
1250+
if (!fir::isPointerType(fir::getBase(result).getType())) {
1251+
resultEntity = loadTrivialScalar(loc, builder, resultEntity);
1252+
1253+
if (resultEntity.isVariable()) {
1254+
// Function result must not be freed, since it is allocated on the stack.
1255+
// Note that in non-elemental case, genCallOpAndResult()
1256+
// is responsible for establishing the clean-up that destroys
1257+
// the derived type result or deallocates its components
1258+
// without finalization.
1259+
auto asExpr = builder.create<hlfir::AsExprOp>(
1260+
loc, resultEntity, /*mustFree=*/builder.createBool(loc, false));
1261+
resultEntity = hlfir::EntityWithAttributes{asExpr.getResult()};
1262+
}
1263+
}
1264+
return hlfir::EntityWithAttributes{resultEntity};
12371265
}
12381266

12391267
/// Create an optional dummy argument value from an entity that may be

flang/lib/Lower/ConvertVariable.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1927,8 +1927,13 @@ void Fortran::lower::mapSymbolAttributes(
19271927
if (ba.isChar()) {
19281928
if (arg) {
19291929
assert(!preAlloc && "dummy cannot be pre-allocated");
1930-
if (arg.getType().isa<fir::BoxCharType>())
1930+
if (arg.getType().isa<fir::BoxCharType>()) {
19311931
std::tie(addr, len) = charHelp.createUnboxChar(arg);
1932+
// Ensure proper type is given to array/scalar that transited via
1933+
// fir.boxchar arg.
1934+
mlir::Type castTy = builder.getRefType(converter.genType(var));
1935+
addr = builder.createConvert(loc, castTy, addr);
1936+
}
19321937
}
19331938
if (std::optional<int64_t> cstLen = ba.getCharLenConst()) {
19341939
// Static length
@@ -1954,13 +1959,6 @@ void Fortran::lower::mapSymbolAttributes(
19541959
}
19551960
}
19561961

1957-
if (addr && addr.getDefiningOp<fir::UnboxCharOp>()) {
1958-
// Ensure proper type is given to array/scalar that transited via
1959-
// fir.boxchar arg.
1960-
mlir::Type castTy = builder.getRefType(converter.genType(var));
1961-
addr = builder.createConvert(loc, castTy, addr);
1962-
}
1963-
19641962
// Compute array extents and lower bounds.
19651963
if (ba.isArray()) {
19661964
if (ba.isStaticArray()) {

0 commit comments

Comments
 (0)