Skip to content

Commit 8892e09

Browse files
SC llvm teamSC llvm team
authored andcommitted
Merged main:b3fbb67379a4 into amd-gfx:6fa5d2831ccc
Local branch amd-gfx 6fa5d28 Merged main:6ade5183232d into amd-gfx:d5105ae3c5a9 Remote branch main b3fbb67 [mlir][sparse] cleanup of COO (llvm#69239)
2 parents 6fa5d28 + b3fbb67 commit 8892e09

File tree

66 files changed

+1161
-947
lines changed

Some content is hidden

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

66 files changed

+1161
-947
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,11 @@ Bug Fixes to C++ Support
513513
rather than prefer the non-templated constructor as specified in
514514
[standard.group]p3.
515515

516+
- Fix a bug where implicit deduction guides are not correctly generated for nested template
517+
classes. Fixes:
518+
(`#46200 <https://github.com/llvm/llvm-project/issues/46200>`_)
519+
(`#57812 <https://github.com/llvm/llvm-project/issues/57812>`_)
520+
516521
Bug Fixes to AST Handling
517522
^^^^^^^^^^^^^^^^^^^^^^^^^
518523
- Fixed an import failure of recursive friend class template.
@@ -521,6 +526,8 @@ Bug Fixes to AST Handling
521526
computed RecordLayout is incorrect if fields are not completely imported and
522527
should not be cached.
523528
`Issue 64170 <https://github.com/llvm/llvm-project/issues/64170>`_
529+
- Fixed ``hasAnyBase`` not binding nodes in its submatcher.
530+
(`#65421 <https://github.com/llvm/llvm-project/issues/65421>`_)
524531

525532
Miscellaneous Bug Fixes
526533
^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/ASTMatchers/ASTMatchersInternal.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ bool matchesAnyBase(const CXXRecordDecl &Node,
8787
[Finder, Builder, &BaseSpecMatcher](const CXXBaseSpecifier *BaseSpec,
8888
CXXBasePath &IgnoredParam) {
8989
BoundNodesTreeBuilder Result(*Builder);
90-
if (BaseSpecMatcher.matches(*BaseSpec, Finder, Builder)) {
90+
if (BaseSpecMatcher.matches(*BaseSpec, Finder, &Result)) {
9191
*Builder = std::move(Result);
9292
return true;
9393
}

clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
//===----------------------------------------------------------------------===//
1313

1414
#include <algorithm>
15-
#include <memory>
1615
#include <optional>
1716
#include <system_error>
1817
#include <utility>
@@ -33,8 +32,8 @@
3332
#include "clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h"
3433
#include "clang/Analysis/FlowSensitive/Value.h"
3534
#include "llvm/ADT/ArrayRef.h"
36-
#include "llvm/ADT/DenseSet.h"
3735
#include "llvm/ADT/STLExtras.h"
36+
#include "llvm/ADT/SmallBitVector.h"
3837
#include "llvm/Support/Debug.h"
3938
#include "llvm/Support/Error.h"
4039

@@ -53,19 +52,14 @@ static int blockIndexInPredecessor(const CFGBlock &Pred,
5352
return BlockPos - Pred.succ_begin();
5453
}
5554

56-
static bool isLoopHead(const CFGBlock &B) {
57-
if (const auto *T = B.getTerminatorStmt())
58-
switch (T->getStmtClass()) {
59-
case Stmt::WhileStmtClass:
60-
case Stmt::DoStmtClass:
61-
case Stmt::ForStmtClass:
62-
case Stmt::CXXForRangeStmtClass:
63-
return true;
64-
default:
65-
return false;
66-
}
67-
68-
return false;
55+
// A "backedge" node is a block introduced in the CFG exclusively to indicate a
56+
// loop backedge. They are exactly identified by the presence of a non-null
57+
// pointer to the entry block of the loop condition. Note that this is not
58+
// necessarily the block with the loop statement as terminator, because
59+
// short-circuit operators will result in multiple blocks encoding the loop
60+
// condition, only one of which will contain the loop statement as terminator.
61+
static bool isBackedgeNode(const CFGBlock &B) {
62+
return B.getLoopTarget() != nullptr;
6963
}
7064

7165
namespace {
@@ -502,14 +496,15 @@ runTypeErasedDataflowAnalysis(
502496
PostVisitCFG) {
503497
PrettyStackTraceAnalysis CrashInfo(CFCtx, "runTypeErasedDataflowAnalysis");
504498

505-
PostOrderCFGView POV(&CFCtx.getCFG());
506-
ForwardDataflowWorklist Worklist(CFCtx.getCFG(), &POV);
499+
const clang::CFG &CFG = CFCtx.getCFG();
500+
PostOrderCFGView POV(&CFG);
501+
ForwardDataflowWorklist Worklist(CFG, &POV);
507502

508503
std::vector<std::optional<TypeErasedDataflowAnalysisState>> BlockStates(
509-
CFCtx.getCFG().size());
504+
CFG.size());
510505

511506
// The entry basic block doesn't contain statements so it can be skipped.
512-
const CFGBlock &Entry = CFCtx.getCFG().getEntry();
507+
const CFGBlock &Entry = CFG.getEntry();
513508
BlockStates[Entry.getBlockID()] = {Analysis.typeErasedInitialElement(),
514509
InitEnv.fork()};
515510
Worklist.enqueueSuccessors(&Entry);
@@ -553,7 +548,7 @@ runTypeErasedDataflowAnalysis(
553548
llvm::errs() << "Old Env:\n";
554549
OldBlockState->Env.dump();
555550
});
556-
if (isLoopHead(*Block)) {
551+
if (isBackedgeNode(*Block)) {
557552
LatticeJoinEffect Effect1 = Analysis.widenTypeErased(
558553
NewBlockState.Lattice, OldBlockState->Lattice);
559554
LatticeJoinEffect Effect2 =

clang/lib/Sema/SemaInit.cpp

Lines changed: 7 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "clang/AST/ExprCXX.h"
1616
#include "clang/AST/ExprObjC.h"
1717
#include "clang/AST/ExprOpenMP.h"
18+
#include "clang/AST/IgnoreExpr.h"
1819
#include "clang/AST/TypeLoc.h"
1920
#include "clang/Basic/CharInfo.h"
2021
#include "clang/Basic/SourceManager.h"
@@ -170,22 +171,9 @@ static void updateStringLiteralType(Expr *E, QualType Ty) {
170171
while (true) {
171172
E->setType(Ty);
172173
E->setValueKind(VK_PRValue);
173-
if (isa<StringLiteral>(E) || isa<ObjCEncodeExpr>(E)) {
174-
break;
175-
} else if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
176-
E = PE->getSubExpr();
177-
} else if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
178-
assert(UO->getOpcode() == UO_Extension);
179-
E = UO->getSubExpr();
180-
} else if (GenericSelectionExpr *GSE = dyn_cast<GenericSelectionExpr>(E)) {
181-
E = GSE->getResultExpr();
182-
} else if (ChooseExpr *CE = dyn_cast<ChooseExpr>(E)) {
183-
E = CE->getChosenSubExpr();
184-
} else if (PredefinedExpr *PE = dyn_cast<PredefinedExpr>(E)) {
185-
E = PE->getFunctionName();
186-
} else {
187-
llvm_unreachable("unexpected expr in string literal init");
188-
}
174+
if (isa<StringLiteral>(E) || isa<ObjCEncodeExpr>(E))
175+
break;
176+
E = IgnoreParensSingleStep(E);
189177
}
190178
}
191179

@@ -194,20 +182,9 @@ static void updateStringLiteralType(Expr *E, QualType Ty) {
194182
static void updateGNUCompoundLiteralRValue(Expr *E) {
195183
while (true) {
196184
E->setValueKind(VK_PRValue);
197-
if (isa<CompoundLiteralExpr>(E)) {
198-
break;
199-
} else if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
200-
E = PE->getSubExpr();
201-
} else if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
202-
assert(UO->getOpcode() == UO_Extension);
203-
E = UO->getSubExpr();
204-
} else if (GenericSelectionExpr *GSE = dyn_cast<GenericSelectionExpr>(E)) {
205-
E = GSE->getResultExpr();
206-
} else if (ChooseExpr *CE = dyn_cast<ChooseExpr>(E)) {
207-
E = CE->getChosenSubExpr();
208-
} else {
209-
llvm_unreachable("unexpected expr in array compound literal init");
210-
}
185+
if (isa<CompoundLiteralExpr>(E))
186+
break;
187+
E = IgnoreParensSingleStep(E);
211188
}
212189
}
213190

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2250,6 +2250,7 @@ struct ConvertConstructorToDeductionGuideTransform {
22502250

22512251
Sema &SemaRef;
22522252
ClassTemplateDecl *Template;
2253+
ClassTemplateDecl *NestedPattern = nullptr;
22532254

22542255
DeclContext *DC = Template->getDeclContext();
22552256
CXXRecordDecl *Primary = Template->getTemplatedDecl();
@@ -2327,6 +2328,8 @@ struct ConvertConstructorToDeductionGuideTransform {
23272328
if (FTD) {
23282329
Args.addOuterTemplateArguments(SubstArgs);
23292330
Args.addOuterRetainedLevel();
2331+
if (NestedPattern)
2332+
Args.addOuterRetainedLevels(NestedPattern->getTemplateDepth());
23302333
}
23312334

23322335
FunctionProtoTypeLoc FPTL = CD->getTypeSourceInfo()->getTypeLoc()
@@ -2438,10 +2441,17 @@ struct ConvertConstructorToDeductionGuideTransform {
24382441
SmallVector<QualType, 4> ParamTypes;
24392442
const FunctionProtoType *T = TL.getTypePtr();
24402443

2444+
MultiLevelTemplateArgumentList OuterInstantiationArgs;
2445+
if (NestedPattern)
2446+
OuterInstantiationArgs = SemaRef.getTemplateInstantiationArgs(Template);
2447+
24412448
// -- The types of the function parameters are those of the constructor.
24422449
for (auto *OldParam : TL.getParams()) {
24432450
ParmVarDecl *NewParam =
24442451
transformFunctionTypeParam(OldParam, Args, MaterializedTypedefs);
2452+
if (NestedPattern && NewParam)
2453+
NewParam = transformFunctionTypeParam(NewParam, OuterInstantiationArgs,
2454+
MaterializedTypedefs);
24452455
if (!NewParam)
24462456
return QualType();
24472457
ParamTypes.push_back(NewParam->getType());
@@ -2647,13 +2657,23 @@ void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template,
26472657
if (BuildingDeductionGuides.isInvalid())
26482658
return;
26492659

2660+
// If the template is nested, then we need to use the original
2661+
// pattern to iterate over the constructors.
2662+
ClassTemplateDecl *Pattern = Transform.Template;
2663+
while (Pattern->getInstantiatedFromMemberTemplate()) {
2664+
if (Pattern->isMemberSpecialization())
2665+
break;
2666+
Pattern = Pattern->getInstantiatedFromMemberTemplate();
2667+
Transform.NestedPattern = Pattern;
2668+
}
2669+
26502670
// Convert declared constructors into deduction guide templates.
26512671
// FIXME: Skip constructors for which deduction must necessarily fail (those
26522672
// for which some class template parameter without a default argument never
26532673
// appears in a deduced context).
26542674
llvm::SmallPtrSet<NamedDecl *, 8> ProcessedCtors;
26552675
bool AddedAny = false;
2656-
for (NamedDecl *D : LookupConstructors(Transform.Primary)) {
2676+
for (NamedDecl *D : LookupConstructors(Pattern->getTemplatedDecl())) {
26572677
D = D->getUnderlyingDecl();
26582678
if (D->isInvalidDecl() || D->isImplicit())
26592679
continue;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %clang_cc1 -std=c++17 -verify %s
2+
// expected-no-diagnostics
3+
4+
template<class T> struct S {
5+
template<class U> struct N {
6+
N(T) {}
7+
N(T, U) {}
8+
template<class V> N(V, U) {}
9+
};
10+
};
11+
12+
S<int>::N x{"a", 1};

clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "ASTMatchersTest.h"
1010
#include "clang/AST/Attrs.inc"
11+
#include "clang/AST/DeclCXX.h"
1112
#include "clang/AST/PrettyPrinter.h"
1213
#include "clang/ASTMatchers/ASTMatchFinder.h"
1314
#include "clang/ASTMatchers/ASTMatchers.h"
@@ -5457,6 +5458,18 @@ TEST(HasParent, NoDuplicateParents) {
54575458
stmt().bind("node"), std::make_unique<HasDuplicateParents>()));
54585459
}
54595460

5461+
TEST(HasAnyBase, BindsInnerBoundNodes) {
5462+
EXPECT_TRUE(matchAndVerifyResultTrue(
5463+
"struct Inner {}; struct Proxy : Inner {}; struct Main : public "
5464+
"Proxy {};",
5465+
cxxRecordDecl(hasName("Main"),
5466+
hasAnyBase(cxxBaseSpecifier(hasType(
5467+
cxxRecordDecl(hasName("Inner")).bind("base-class")))))
5468+
.bind("class"),
5469+
std::make_unique<VerifyIdIsBoundTo<CXXRecordDecl>>("base-class",
5470+
"Inner")));
5471+
}
5472+
54605473
TEST(TypeMatching, PointeeTypes) {
54615474
EXPECT_TRUE(matches("int b; int &a = b;",
54625475
referenceType(pointee(builtinType()))));

clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4099,6 +4099,20 @@ TEST(TransferTest, LoopDereferencingChangingRecordPointerConverges) {
40994099
ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
41004100
}
41014101

4102+
TEST(TransferTest, LoopWithShortCircuitedConditionConverges) {
4103+
std::string Code = R"cc(
4104+
bool foo();
4105+
4106+
void target() {
4107+
bool c = false;
4108+
while (foo() || foo()) {
4109+
c = true;
4110+
}
4111+
}
4112+
)cc";
4113+
ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4114+
}
4115+
41024116
TEST(TransferTest, DoesNotCrashOnUnionThisExpr) {
41034117
std::string Code = R"(
41044118
union Union {

clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -912,6 +912,29 @@ TEST_F(FlowConditionTest, WhileStmt) {
912912
});
913913
}
914914

915+
TEST_F(FlowConditionTest, WhileStmtWithAssignmentInCondition) {
916+
std::string Code = R"(
917+
void target(bool Foo) {
918+
// This test checks whether the analysis preserves the connection between
919+
// the value of `Foo` and the assignment expression, despite widening.
920+
// The equality operator generates a fresh boolean variable on each
921+
// interpretation, which forces use of widening.
922+
while ((Foo = (3 == 4))) {
923+
(void)0;
924+
/*[[p]]*/
925+
}
926+
}
927+
)";
928+
runDataflow(
929+
Code,
930+
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
931+
ASTContext &ASTCtx) {
932+
const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
933+
auto &FooVal = getValueForDecl<BoolValue>(ASTCtx, Env, "Foo").formula();
934+
EXPECT_TRUE(Env.flowConditionImplies(FooVal));
935+
});
936+
}
937+
915938
TEST_F(FlowConditionTest, Conjunction) {
916939
std::string Code = R"(
917940
void target(bool Foo, bool Bar) {

flang/lib/Lower/Allocatable.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ class AllocateStmtHelper {
462462
errorManager.genStatCheck(builder, loc);
463463
genAllocateObjectInit(box);
464464
if (alloc.hasCoarraySpec())
465-
TODO(loc, "coarray allocation");
465+
TODO(loc, "coarray: allocation of a coarray object");
466466
if (alloc.type.IsPolymorphic())
467467
genSetType(alloc, box, loc);
468468
genSetDeferredLengthParameters(alloc, box);
@@ -582,7 +582,7 @@ class AllocateStmtHelper {
582582
errorManager.genStatCheck(builder, loc);
583583
genAllocateObjectInit(box);
584584
if (alloc.hasCoarraySpec())
585-
TODO(loc, "coarray allocation");
585+
TODO(loc, "coarray: allocation of a coarray object");
586586
// Set length of the allocate object if it has. Otherwise, get the length
587587
// from source for the deferred length parameter.
588588
if (lenParams.empty() && box.isCharacter() &&

flang/lib/Lower/Bridge.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2625,35 +2625,35 @@ class FirConverter : public Fortran::lower::AbstractConverter {
26252625
}
26262626

26272627
void genFIR(const Fortran::parser::ChangeTeamConstruct &construct) {
2628-
TODO(toLocation(), "ChangeTeamConstruct implementation");
2628+
TODO(toLocation(), "coarray: ChangeTeamConstruct");
26292629
}
26302630
void genFIR(const Fortran::parser::ChangeTeamStmt &stmt) {
2631-
TODO(toLocation(), "ChangeTeamStmt implementation");
2631+
TODO(toLocation(), "coarray: ChangeTeamStmt");
26322632
}
26332633
void genFIR(const Fortran::parser::EndChangeTeamStmt &stmt) {
2634-
TODO(toLocation(), "EndChangeTeamStmt implementation");
2634+
TODO(toLocation(), "coarray: EndChangeTeamStmt");
26352635
}
26362636

26372637
void genFIR(const Fortran::parser::CriticalConstruct &criticalConstruct) {
26382638
setCurrentPositionAt(criticalConstruct);
2639-
TODO(toLocation(), "CriticalConstruct implementation");
2639+
TODO(toLocation(), "coarray: CriticalConstruct");
26402640
}
26412641
void genFIR(const Fortran::parser::CriticalStmt &) {
2642-
TODO(toLocation(), "CriticalStmt implementation");
2642+
TODO(toLocation(), "coarray: CriticalStmt");
26432643
}
26442644
void genFIR(const Fortran::parser::EndCriticalStmt &) {
2645-
TODO(toLocation(), "EndCriticalStmt implementation");
2645+
TODO(toLocation(), "coarray: EndCriticalStmt");
26462646
}
26472647

26482648
void genFIR(const Fortran::parser::SelectRankConstruct &selectRankConstruct) {
26492649
setCurrentPositionAt(selectRankConstruct);
2650-
TODO(toLocation(), "SelectRankConstruct implementation");
2650+
TODO(toLocation(), "coarray: SelectRankConstruct");
26512651
}
26522652
void genFIR(const Fortran::parser::SelectRankStmt &) {
2653-
TODO(toLocation(), "SelectRankStmt implementation");
2653+
TODO(toLocation(), "coarray: SelectRankStmt");
26542654
}
26552655
void genFIR(const Fortran::parser::SelectRankCaseStmt &) {
2656-
TODO(toLocation(), "SelectRankCaseStmt implementation");
2656+
TODO(toLocation(), "coarray: SelectRankCaseStmt");
26572657
}
26582658

26592659
void genFIR(const Fortran::parser::SelectTypeConstruct &selectTypeConstruct) {

flang/lib/Lower/CallInterface.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -952,7 +952,7 @@ class Fortran::lower::CallInterfaceImpl {
952952
if (shapeAttrs.test(ShapeAttr::AssumedRank))
953953
TODO(loc, "assumed rank in procedure interface");
954954
if (shapeAttrs.test(ShapeAttr::Coarray))
955-
TODO(loc, "coarray in procedure interface");
955+
TODO(loc, "coarray: dummy argument coarray in procedure interface");
956956

957957
// So far assume that if the argument cannot be passed by implicit interface
958958
// it must be by box. That may no be always true (e.g for simple optionals)

0 commit comments

Comments
 (0)