Skip to content

Commit d4f0f43

Browse files
authored
[Clang] Fix the access checking for non-aggregates in default arguments (#141207)
We check the accessibility of constructors when initializing a default argument whose type is not an aggregate. Make sure the check is performed within the correct DeclContext. Otherwise, it will be delayed until the end of the declaration, at which point the context is mismatched. Fixes #62444 Fixes #83608
1 parent 989aadf commit d4f0f43

File tree

3 files changed

+54
-7
lines changed

3 files changed

+54
-7
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,7 @@ Bug Fixes to C++ Support
794794
- Clang could incorrectly instantiate functions in discarded contexts (#GH140449)
795795
- Fix instantiation of default-initialized variable template specialization. (#GH140632) (#GH140622)
796796
- Clang modules now allow a module and its user to differ on TrivialAutoVarInit*
797+
- Fixed an access checking bug when initializing non-aggregates in default arguments (#GH62444), (#GH83608)
797798

798799
Bug Fixes to AST Handling
799800
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaTemplateInstantiate.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3340,21 +3340,21 @@ bool Sema::SubstDefaultArgument(
33403340
}
33413341

33423342
ExprResult Result;
3343+
// C++ [dcl.fct.default]p5:
3344+
// The names in the [default argument] expression are bound, and
3345+
// the semantic constraints are checked, at the point where the
3346+
// default argument expression appears.
3347+
ContextRAII SavedContext(*this, FD);
33433348
{
3344-
// C++ [dcl.fct.default]p5:
3345-
// The names in the [default argument] expression are bound, and
3346-
// the semantic constraints are checked, at the point where the
3347-
// default argument expression appears.
3348-
ContextRAII SavedContext(*this, FD);
3349-
std::unique_ptr<LocalInstantiationScope> LIS;
3349+
std::optional<LocalInstantiationScope> LIS;
33503350

33513351
if (ForCallExpr) {
33523352
// When instantiating a default argument due to use in a call expression,
33533353
// an instantiation scope that includes the parameters of the callee is
33543354
// required to satisfy references from the default argument. For example:
33553355
// template<typename T> void f(T a, int = decltype(a)());
33563356
// void g() { f(0); }
3357-
LIS = std::make_unique<LocalInstantiationScope>(*this);
3357+
LIS.emplace(*this);
33583358
FunctionDecl *PatternFD = FD->getTemplateInstantiationPattern(
33593359
/*ForDefinition*/ false);
33603360
if (addInstantiatedParametersToScope(FD, PatternFD, *LIS, TemplateArgs))

clang/test/SemaCXX/access-control-check.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,49 @@ class N : M,P {
1313
N() {}
1414
int PR() { return iP + PPR(); } // expected-error 2 {{private member of 'P'}}
1515
};
16+
17+
namespace GH83608 {
18+
19+
class single;
20+
21+
class check_constructible {
22+
// This makes the class a non-aggregate, which enforces us to check
23+
// the constructor when initializing.
24+
check_constructible() {}
25+
26+
friend class single;
27+
};
28+
29+
struct single {
30+
template <class T> single(T u, check_constructible = {}) {}
31+
};
32+
33+
// We perform access checking when substituting into the default argument.
34+
// Make sure it runs within the context of 'single'.
35+
single x(0);
36+
37+
}
38+
39+
namespace GH62444 {
40+
41+
struct B {
42+
friend struct A;
43+
private:
44+
B(int); // #B
45+
};
46+
47+
template<class T>
48+
int f(T = 0); // #Decl
49+
50+
struct A {
51+
A() {
52+
int i = f<B>();
53+
// expected-error@#Decl {{calling a private constructor}}
54+
// expected-note@-2 {{in instantiation of default function argument}}
55+
// expected-note@#B {{declared private}}
56+
}
57+
};
58+
59+
int i = f<B>();
60+
61+
}

0 commit comments

Comments
 (0)