Skip to content

Commit b7394ba

Browse files
authored
Merge branch 'llvm:main' into stmt-attributes
2 parents a445081 + 25d9688 commit b7394ba

File tree

62 files changed

+1586
-820
lines changed

Some content is hidden

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

62 files changed

+1586
-820
lines changed

clang-tools-extra/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -148,11 +148,8 @@ groupReplacements(const TUReplacements &TUs, const TUDiagnostics &TUDs,
148148

149149
if (auto Entry = SM.getFileManager().getOptionalFileRef(Path)) {
150150
if (SourceTU) {
151-
auto &Replaces = DiagReplacements[*Entry];
152-
auto It = Replaces.find(R);
153-
if (It == Replaces.end())
154-
Replaces.emplace(R, SourceTU);
155-
else if (It->second != SourceTU)
151+
auto [It, Inserted] = DiagReplacements[*Entry].try_emplace(R, SourceTU);
152+
if (!Inserted && It->second != SourceTU)
156153
// This replacement is a duplicate of one suggested by another TU.
157154
return;
158155
}

clang-tools-extra/clang-change-namespace/ChangeNamespace.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -606,9 +606,8 @@ void ChangeNamespaceTool::run(
606606
Result.Nodes.getNodeAs<DeclRefExpr>("func_ref")) {
607607
// If this reference has been processed as a function call, we do not
608608
// process it again.
609-
if (ProcessedFuncRefs.count(FuncRef))
609+
if (!ProcessedFuncRefs.insert(FuncRef).second)
610610
return;
611-
ProcessedFuncRefs.insert(FuncRef);
612611
const auto *Func = Result.Nodes.getNodeAs<FunctionDecl>("func_decl");
613612
assert(Func);
614613
const auto *Context = Result.Nodes.getNodeAs<Decl>("dc");

clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,12 +146,13 @@ void ForwardDeclarationNamespaceCheck::onEndOfTranslationUnit() {
146146
}
147147
// Check if a definition in another namespace exists.
148148
const auto DeclName = CurDecl->getName();
149-
if (!DeclNameToDefinitions.contains(DeclName)) {
149+
auto It = DeclNameToDefinitions.find(DeclName);
150+
if (It == DeclNameToDefinitions.end()) {
150151
continue; // No definition in this translation unit, we can skip it.
151152
}
152153
// Make a warning for each definition with the same name (in other
153154
// namespaces).
154-
const auto &Definitions = DeclNameToDefinitions[DeclName];
155+
const auto &Definitions = It->second;
155156
for (const auto *Def : Definitions) {
156157
diag(CurDecl->getLocation(),
157158
"no definition found for %0, but a definition with "

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,9 @@ C++23 Feature Support
171171
^^^^^^^^^^^^^^^^^^^^^
172172
- Removed the restriction to literal types in constexpr functions in C++23 mode.
173173

174+
- Extend lifetime of temporaries in mem-default-init for P2718R0. Clang now fully
175+
supported `P2718R0 Lifetime extension in range-based for loops <https://wg21.link/P2718R0>`_.
176+
174177
C++20 Feature Support
175178
^^^^^^^^^^^^^^^^^^^^^
176179

clang/lib/Analysis/ProgramPoint.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ void ProgramPoint::printJson(llvm::raw_ostream &Out, const char *NL) const {
157157
LHS->printJson(Out, nullptr, PP, AddQuotes);
158158
} else {
159159
Out << "null";
160-
}
160+
}
161161

162162
Out << ", \"rhs\": ";
163163
if (const Stmt *RHS = C->getRHS()) {

clang/lib/Sema/SemaExpr.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5649,6 +5649,8 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) {
56495649
runWithSufficientStackSpace(Loc, [&] {
56505650
MarkDeclarationsReferencedInExpr(E, /*SkipLocalVariables=*/false);
56515651
});
5652+
if (isInLifetimeExtendingContext())
5653+
DiscardCleanupsInEvaluationContext();
56525654
// C++11 [class.base.init]p7:
56535655
// The initialization of each base and member constitutes a
56545656
// full-expression.

clang/lib/Sema/SemaInit.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,8 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
763763
SemaRef.currentEvaluationContext().DelayedDefaultInitializationContext =
764764
SemaRef.parentEvaluationContext()
765765
.DelayedDefaultInitializationContext;
766+
SemaRef.currentEvaluationContext().InLifetimeExtendingContext =
767+
SemaRef.parentEvaluationContext().InLifetimeExtendingContext;
766768
DIE = SemaRef.BuildCXXDefaultInitExpr(Loc, Field);
767769
}
768770
if (DIE.isInvalid()) {

clang/test/AST/ast-dump-for-range-lifetime.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,4 +449,63 @@ void test13() {
449449
for (auto e : dg<A>().r().g().r().g().r().g())
450450
bar(e);
451451
}
452+
453+
extern "C" void exit(int);
454+
455+
struct A14 {
456+
int arr[1];
457+
~A14() noexcept(false) { throw 42; }
458+
};
459+
460+
struct B14 {
461+
int x;
462+
const A14 &a = A14{{0}};
463+
const int *begin() { return a.arr; }
464+
const int *end() { return &a.arr[1]; }
465+
};
466+
467+
void test14() {
468+
// The ExprWithCleanups in CXXDefaultInitExpr will be ignored.
469+
470+
// CHECK: FunctionDecl {{.*}} test14 'void ()'
471+
// CHECK: -CXXForRangeStmt {{.*}}
472+
// CHECK-NEXT: |-<<<NULL>>>
473+
// CHECK-NEXT: |-DeclStmt {{.*}}
474+
// CHECK-NEXT: | `-VarDecl {{.*}} implicit used __range1 'const int (&)[1]' cinit
475+
// CHECK-NEXT: | `-ExprWithCleanups {{.*}} 'const int[1]' lvalue
476+
// CHECK-NEXT: | `-MemberExpr {{.*}} 'const int[1]' lvalue .arr {{.*}}
477+
// CHECK-NEXT: | `-MemberExpr {{.*}} 'const A14':'const P2718R0::A14' lvalue .a {{.*}}
478+
// CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'B14':'P2718R0::B14' xvalue extended by Var {{.*}} '__range1' 'const int (&)[1]'
479+
// CHECK-NEXT: | `-CXXFunctionalCastExpr {{.*}} 'B14':'P2718R0::B14' functional cast to B14 <NoOp>
480+
// CHECK-NEXT: | `-InitListExpr {{.*}} 'B14':'P2718R0::B14'
481+
// CHECK-NEXT: | |-IntegerLiteral {{.*}} 'int' 0
482+
// CHECK-NEXT: | `-CXXDefaultInitExpr {{.*}} 'const A14':'const P2718R0::A14' lvalue has rewritten init
483+
// CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const A14':'const P2718R0::A14' lvalue extended by Var {{.*}} '__range1' 'const int (&)[1]'
484+
// CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'const A14':'const P2718R0::A14' <NoOp>
485+
// CHECK-NEXT: | `-CXXFunctionalCastExpr {{.*}} 'A14':'P2718R0::A14' functional cast to A14 <NoOp>
486+
// CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A14':'P2718R0::A14' (CXXTemporary {{.*}})
487+
// CHECK-NEXT: | `-InitListExpr {{.*}} 'A14':'P2718R0::A14'
488+
// CHECK-NEXT: | `-InitListExpr {{.*}} 'int[1]'
489+
// CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 0
490+
for (auto &&x : B14{0}.a.arr) { exit(0); }
491+
492+
// CHECK: -CXXForRangeStmt {{.*}}
493+
// CHECK-NEXT: |-<<<NULL>>>
494+
// CHECK-NEXT: |-DeclStmt {{.*}}
495+
// CHECK-NEXT: | `-VarDecl {{.*}} col:19 implicit used __range1 'B14 &&' cinit
496+
// CHECK-NEXT: | `-ExprWithCleanups {{.*}} 'B14':'P2718R0::B14' xvalue
497+
// CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'B14':'P2718R0::B14' xvalue extended by Var {{.*}} '__range1' 'B14 &&'
498+
// CHECK-NEXT: | `-CXXFunctionalCastExpr {{.*}} 'B14':'P2718R0::B14' functional cast to B14 <NoOp>
499+
// CHECK-NEXT: | `-InitListExpr {{.*}} 'B14':'P2718R0::B14'
500+
// CHECK-NEXT: | |-IntegerLiteral {{.*}} 'int' 0
501+
// CHECK-NEXT: | `-CXXDefaultInitExpr {{.*}} 'const A14':'const P2718R0::A14' lvalue has rewritten init
502+
// CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const A14':'const P2718R0::A14' lvalue extended by Var {{.*}} '__range1' 'B14 &&'
503+
// CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'const A14':'const P2718R0::A14' <NoOp>
504+
// CHECK-NEXT: | `-CXXFunctionalCastExpr {{.*}} 'A14':'P2718R0::A14' functional cast to A14 <NoOp>
505+
// CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A14':'P2718R0::A14' (CXXTemporary {{.*}})
506+
// CHECK-NEXT: | `-InitListExpr {{.*}} 'A14':'P2718R0::A14'
507+
// CHECK-NEXT: | `-InitListExpr {{.*}} 'int[1]'
508+
// CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 0
509+
for (auto &&x : B14{0}) { exit(0); }
510+
}
452511
} // namespace P2718R0

clang/test/CXX/special/class.temporary/p6.cpp

Lines changed: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,80 @@ template void default_arg_dependent_context2<int>();
463463
template void default_arg_dependent_context3<int>();
464464
} // namespace default_arg
465465

466+
namespace default_init {
467+
template <class T>
468+
struct DepA {
469+
T arr[1];
470+
~DepA() {}
471+
};
472+
473+
template <class T>
474+
struct DepB {
475+
int x;
476+
const DepA<T> &a = DepA<T>{{0}};
477+
~DepB() {}
478+
const int *begin() { return a.arr; }
479+
const int *end() { return &a.arr[1]; }
480+
};
481+
482+
template <typename T>
483+
void default_init1_dependent() {
484+
// CHECK-CXX23: void @_ZN7P2718R012default_init23default_init1_dependentINS0_4DepBIiEEEEvv()
485+
// CHECK-CXX23-LABEL: for.cond.cleanup:
486+
// CHECK-CXX23-NEXT: call void @_ZN7P2718R012default_init4DepBIiED1Ev(
487+
// CHECK-CXX23-NEXT: call void @_ZN7P2718R012default_init4DepAIiED1Ev(
488+
for (auto &&x : T{0}) {}
489+
}
490+
491+
template <typename T>
492+
void default_init2_dependent() {
493+
// CHECK-CXX23: void @_ZN7P2718R012default_init23default_init2_dependentINS0_4DepBIiEEEEvv()
494+
// CHECK-CXX23-LABEL: for.cond.cleanup:
495+
// CHECK-CXX23-NEXT: call void @_ZN7P2718R012default_init4DepBIiED1Ev(
496+
// CHECK-CXX23-NEXT: call void @_ZN7P2718R012default_init4DepAIiED1Ev(
497+
for (auto &&x : T{0}.a.arr) {}
498+
}
499+
500+
template void default_init1_dependent<DepB<int>>();
501+
template void default_init2_dependent<DepB<int>>();
502+
} // namespace default_init
503+
504+
// -- Examples from https://wg21.link/p2718r0
505+
extern void block_scope_begin_function();
506+
extern void block_scope_end_function();
507+
namespace std_examples {
508+
using T = std::list<int>;
509+
const T& f1(const T& t) { return t; }
510+
const T& f2(T t) { return t; }
511+
T g();
512+
void foo() {
513+
// CHECK-CXX23: define {{.*}} void @_ZN7P2718R012std_examples3fooEv()
514+
// CHECK-CXX23: call void @_ZN7P2718R026block_scope_begin_functionEv
515+
block_scope_begin_function();
516+
{
517+
// CHECK-CXX23-NEXT: call void @_ZN7P2718R012std_examples1gEv
518+
// CHECK-CXX23-NEXT: call {{.*}} @_ZN7P2718R012std_examples2f1ERKSt4listIiE
519+
// CHECK-CXX23: for.cond.cleanup:
520+
// CHECK-CXX23-NEXT: call void @_ZNSt4listIiED1Ev
521+
for (auto e : f1(g())) {} // OK, lifetime of return value of g() extended
522+
}
523+
// CHECK-CXX23: call void @_ZN7P2718R024block_scope_end_functionEv
524+
block_scope_end_function();
525+
526+
// The lifetime of temporary returned by g() in this case will not be extended.
527+
// CHECK-CXX23: call void @_ZN7P2718R026block_scope_begin_functionEv
528+
block_scope_begin_function();
529+
{
530+
// CHECK-CXX23-NEXT: call void @_ZN7P2718R012std_examples1gEv
531+
// CHECK-CXX23-NEXT: call {{.*}} @_ZN7P2718R012std_examples2f2ESt4listIiE
532+
// CHECK-CXX23-NEXT: call void @_ZNSt4listIiED1Ev
533+
for (auto e : f2(g())) {} // undefined behavior
534+
}
535+
// CHECK-CXX23: call void @_ZN7P2718R024block_scope_end_functionEv
536+
block_scope_end_function();
537+
}
538+
} // namespace std_examples
539+
466540
namespace basic {
467541
using T = std::list<int>;
468542
const T& f1(const T& t) { return t; }
@@ -579,5 +653,51 @@ void default_arg3() {
579653
for (auto e : C(0, C(0, C(0, C())))) {}
580654
}
581655
} // namespace default_arg
582-
} // namespace P2718R0
583656

657+
namespace default_init {
658+
struct X {
659+
int x;
660+
~X() {}
661+
};
662+
663+
struct Y {
664+
int y;
665+
const X &x = X{1};
666+
~Y() {}
667+
};
668+
669+
struct A {
670+
int arr[1];
671+
const Y &y = Y{1};
672+
~A() {}
673+
};
674+
675+
struct B {
676+
int x;
677+
const A &a = A{{0}};
678+
~B() {}
679+
const int *begin() { return a.arr; }
680+
const int *end() { return &a.arr[1]; }
681+
};
682+
683+
void default_init1() {
684+
// CHECK-CXX23: void @_ZN7P2718R012default_init13default_init1Ev()
685+
// CHECK-CXX23-LABEL: for.cond.cleanup:
686+
// CHECK-CXX23-NEXT: call void @_ZN7P2718R012default_init1BD1Ev(
687+
// CHECK-CXX23-NEXT: call void @_ZN7P2718R012default_init1AD1Ev(
688+
// CHECK-CXX23-NEXT: call void @_ZN7P2718R012default_init1YD1Ev(
689+
// CHECK-CXX23-NEXT: call void @_ZN7P2718R012default_init1XD1Ev(
690+
for (auto &&x : B{0}) {}
691+
}
692+
693+
void default_init2() {
694+
// CHECK-CXX23: void @_ZN7P2718R012default_init13default_init2Ev()
695+
// CHECK-CXX23-LABEL: for.cond.cleanup:
696+
// CHECK-CXX23-NEXT: call void @_ZN7P2718R012default_init1BD1Ev(
697+
// CHECK-CXX23-NEXT: call void @_ZN7P2718R012default_init1AD1Ev(
698+
// CHECK-CXX23-NEXT: call void @_ZN7P2718R012default_init1YD1Ev(
699+
// CHECK-CXX23-NEXT: call void @_ZN7P2718R012default_init1XD1Ev(
700+
for (auto &&x : B{0}.a.arr) {}
701+
}
702+
} // namespace default_init
703+
} // namespace P2718R0

clang/test/SemaCXX/attr-lifetimebound.cpp

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -75,23 +75,26 @@ namespace usage_ok {
7575
}
7676
}
7777

78-
# 1 "<std>" 1 3
7978
namespace std {
8079
using size_t = __SIZE_TYPE__;
81-
struct string {
82-
string();
83-
string(const char*);
80+
template<typename T>
81+
struct basic_string {
82+
basic_string();
83+
basic_string(const T*);
8484

8585
char &operator[](size_t) const [[clang::lifetimebound]];
8686
};
87-
string operator""s(const char *, size_t);
88-
89-
struct string_view {
90-
string_view();
91-
string_view(const char *p [[clang::lifetimebound]]);
92-
string_view(const string &s [[clang::lifetimebound]]);
87+
using string = basic_string<char>;
88+
string operator""s(const char *, size_t); // expected-warning {{user-defined literal suffixes not starting with '_' are reserved}}
89+
90+
template<typename T>
91+
struct basic_string_view {
92+
basic_string_view();
93+
basic_string_view(const T *p);
94+
basic_string_view(const string &s [[clang::lifetimebound]]);
9395
};
94-
string_view operator""sv(const char *, size_t);
96+
using string_view = basic_string_view<char>;
97+
string_view operator""sv(const char *, size_t); // expected-warning {{user-defined literal suffixes not starting with '_' are reserved}}
9598

9699
struct vector {
97100
int *data();
@@ -100,7 +103,6 @@ namespace std {
100103

101104
template<typename K, typename V> struct map {};
102105
}
103-
# 68 "attr-lifetimebound.cpp" 2
104106

105107
using std::operator""s;
106108
using std::operator""sv;
@@ -112,7 +114,7 @@ namespace p0936r0_examples {
112114
void f() {
113115
std::string_view sv = "hi";
114116
std::string_view sv2 = sv + sv; // expected-warning {{temporary}}
115-
sv2 = sv + sv; // FIXME: can we infer that we should warn here too?
117+
sv2 = sv + sv; // expected-warning {{object backing the pointer}}
116118
}
117119

118120
struct X { int a, b; };
@@ -238,11 +240,6 @@ template <class T> T *addressof(T &arg) {
238240
&const_cast<char &>(reinterpret_cast<const volatile char &>(arg)));
239241
}
240242

241-
template<typename T>
242-
struct basic_string_view {
243-
basic_string_view(const T *);
244-
};
245-
246243
template <class T> struct span {
247244
template<size_t _ArrayExtent>
248245
span(const T (&__arr)[_ArrayExtent]) noexcept;

0 commit comments

Comments
 (0)