Skip to content

Commit 34632d0

Browse files
committed
[Clang] Correct the DeclRefExpr's Type after the initializer gets instantiated
The instantiation of a VarDecl's initializer might be deferred until the variable is actually used. However, we were still building the DeclRefExpr with a type that could later be changed by the initializer's instantiation, which is incorrect when incomplete arrays are involved.
1 parent 849e5ea commit 34632d0

File tree

3 files changed

+34
-4
lines changed

3 files changed

+34
-4
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ Bug Fixes to C++ Support
355355
- Correctly diagnoses if unresolved using declarations shadows template paramters (#GH129411)
356356
- Clang was previously coalescing volatile writes to members of volatile base class subobjects.
357357
The issue has been addressed by propagating qualifiers during derived-to-base conversions in the AST. (#GH127824)
358+
- Correctly propagates the instantiated array type to the ``DeclRefExpr`` that refers to it. (#GH79750), (#GH113936), (#GH133047)
358359
- Fixed a Clang regression in C++20 mode where unresolved dependent call expressions were created inside non-dependent contexts (#GH122892)
359360
- Clang now emits the ``-Wunused-variable`` warning when some structured bindings are unused
360361
and the ``[[maybe_unused]]`` attribute is not applied. (#GH125810)

clang/lib/Sema/SemaExpr.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19849,11 +19849,14 @@ static void DoMarkVarDeclReferenced(
1984919849
SemaRef.InstantiateVariableDefinition(PointOfInstantiation, Var);
1985019850
});
1985119851

19852-
// Re-set the member to trigger a recomputation of the dependence bits
19853-
// for the expression.
19854-
if (auto *DRE = dyn_cast_or_null<DeclRefExpr>(E))
19852+
if (auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
19853+
// Re-set the member to trigger a recomputation of the dependence bits
19854+
// for the expression.
1985519855
DRE->setDecl(DRE->getDecl());
19856-
else if (auto *ME = dyn_cast_or_null<MemberExpr>(E))
19856+
if (SemaRef.Context.getAsIncompleteArrayType(DRE->getType()) &&
19857+
!SemaRef.Context.getAsIncompleteArrayType(Var->getType()))
19858+
DRE->setType(Var->getType());
19859+
} else if (auto *ME = dyn_cast_or_null<MemberExpr>(E))
1985719860
ME->setMemberDecl(ME->getMemberDecl());
1985819861
} else if (FirstInstantiation) {
1985919862
SemaRef.PendingInstantiations

clang/test/SemaCXX/cxx1y-variable-templates_top_level.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,3 +467,29 @@ namespace VexingParse {
467467
template <typename> int var; // expected-note {{declared here}}
468468
int x(var); // expected-error {{use of variable template 'var' requires template arguments}}
469469
}
470+
471+
#ifndef PRECXX11
472+
473+
namespace GH79750 {
474+
475+
enum class Values { A };
476+
477+
template<typename E>
478+
constexpr Values values[] = {E::A};
479+
480+
constexpr auto r = values<Values>[0] == Values::A;
481+
482+
}
483+
484+
namespace GH113956 {
485+
486+
template <class T, T... VALUES>
487+
struct C {
488+
static constexpr T VALUEARRAY[] = {VALUES...};
489+
};
490+
491+
static_assert(C<int, 0,1,2,3,4>::VALUEARRAY[3] == 3, "");
492+
static_assert(C<int, 0,1,2,3,4>::VALUEARRAY[0] == 0, "");
493+
494+
}
495+
#endif

0 commit comments

Comments
 (0)