Skip to content

Commit f9d7619

Browse files
committed
[ASTContext] Profile Dependently-sized array types that do not have a specified number
of elements Close #91105 The root reason for the issue is that we always generate the dependently-sized array types which don't specify a number of elements. The original comment says: > We do no canonicalization here at all, which is okay > because they can't be used in most locations. But now we find the locations.
1 parent 236b3e1 commit f9d7619

File tree

3 files changed

+66
-18
lines changed

3 files changed

+66
-18
lines changed

clang/lib/AST/ASTContext.cpp

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3797,33 +3797,33 @@ QualType ASTContext::getDependentSizedArrayType(QualType elementType,
37973797
numElements->isValueDependent()) &&
37983798
"Size must be type- or value-dependent!");
37993799

3800+
SplitQualType canonElementType = getCanonicalType(elementType).split();
3801+
3802+
void *insertPos = nullptr;
3803+
llvm::FoldingSetNodeID ID;
3804+
DependentSizedArrayType::Profile(
3805+
ID, *this, numElements ? QualType(canonElementType.Ty, 0) : elementType,
3806+
ASM, elementTypeQuals, numElements);
3807+
3808+
// Look for an existing type with these properties.
3809+
DependentSizedArrayType *canonTy =
3810+
DependentSizedArrayTypes.FindNodeOrInsertPos(ID, insertPos);
3811+
38003812
// Dependently-sized array types that do not have a specified number
38013813
// of elements will have their sizes deduced from a dependent
3802-
// initializer. We do no canonicalization here at all, which is okay
3803-
// because they can't be used in most locations.
3814+
// initializer.
38043815
if (!numElements) {
3816+
if (canonTy)
3817+
return QualType(canonTy, 0);
3818+
38053819
auto *newType = new (*this, alignof(DependentSizedArrayType))
38063820
DependentSizedArrayType(elementType, QualType(), numElements, ASM,
38073821
elementTypeQuals, brackets);
3822+
DependentSizedArrayTypes.InsertNode(newType, insertPos);
38083823
Types.push_back(newType);
38093824
return QualType(newType, 0);
38103825
}
38113826

3812-
// Otherwise, we actually build a new type every time, but we
3813-
// also build a canonical type.
3814-
3815-
SplitQualType canonElementType = getCanonicalType(elementType).split();
3816-
3817-
void *insertPos = nullptr;
3818-
llvm::FoldingSetNodeID ID;
3819-
DependentSizedArrayType::Profile(ID, *this,
3820-
QualType(canonElementType.Ty, 0),
3821-
ASM, elementTypeQuals, numElements);
3822-
3823-
// Look for an existing type with these properties.
3824-
DependentSizedArrayType *canonTy =
3825-
DependentSizedArrayTypes.FindNodeOrInsertPos(ID, insertPos);
3826-
38273827
// If we don't have one, build one.
38283828
if (!canonTy) {
38293829
canonTy = new (*this, alignof(DependentSizedArrayType))

clang/lib/AST/Type.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,8 @@ void DependentSizedArrayType::Profile(llvm::FoldingSetNodeID &ID,
256256
ID.AddPointer(ET.getAsOpaquePtr());
257257
ID.AddInteger(llvm::to_underlying(SizeMod));
258258
ID.AddInteger(TypeQuals);
259-
E->Profile(ID, Context, true);
259+
if (E)
260+
E->Profile(ID, Context, true);
260261
}
261262

262263
DependentVectorType::DependentVectorType(QualType ElementType,

clang/test/Modules/pr91105.cppm

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// RUN: rm -rf %t
2+
// RUN: mkdir -p %t
3+
// RUN: split-file %s %t
4+
//
5+
// RUN: %clang_cc1 -std=c++20 %t/bar.cppm -emit-module-interface -o %t/bar.pcm
6+
// RUN: %clang_cc1 -std=c++20 %t/foo.cc -fmodule-file=bar=%t/bar.pcm -fsyntax-only -verify
7+
//
8+
// RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf %t/bar.cppm -emit-module-interface \
9+
// RUN: -o %t/bar.pcm
10+
// RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf %t/foo.cc \
11+
// RUN: -fmodule-file=bar=%t/bar.pcm -fsyntax-only -verify
12+
//
13+
// RUN: %clang_cc1 -std=c++20 %t/bar.cppm -emit-reduced-module-interface -o %t/bar.pcm
14+
// RUN: %clang_cc1 -std=c++20 %t/foo.cc -fmodule-file=bar=%t/bar.pcm -fsyntax-only -verify
15+
//
16+
// RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf %t/bar.cppm -emit-reduced-module-interface \
17+
// RUN: -o %t/bar.pcm
18+
// RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf %t/foo.cc \
19+
// RUN: -fmodule-file=bar=%t/bar.pcm -fsyntax-only -verify
20+
21+
//--- h.hpp
22+
#pragma once
23+
24+
struct T {
25+
constexpr T(const char *) {}
26+
};
27+
template <char... c>
28+
struct t {
29+
inline constexpr operator T() const { return {s}; }
30+
31+
private:
32+
inline static constexpr char s[]{c..., '\0'};
33+
};
34+
35+
//--- bar.cppm
36+
module;
37+
#include "h.hpp"
38+
export module bar;
39+
export inline constexpr auto k = t<'k'>{};
40+
41+
//--- foo.cc
42+
// expected-no-diagnostics
43+
#include "h.hpp"
44+
import bar;
45+
void f() {
46+
T x = k;
47+
}

0 commit comments

Comments
 (0)