Skip to content

Commit a36e3e7

Browse files
committed
[Clang] Fix missed initializer instantiation bug for variable templates
[Clang] Fix missed initializer instantiation bug for variable templates
1 parent 9b10512 commit a36e3e7

File tree

5 files changed

+39
-12
lines changed

5 files changed

+39
-12
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,7 @@ Bug Fixes to C++ Support
604604
- Clang now issues an error when placement new is used to modify a const-qualified variable
605605
in a ``constexpr`` function. (#GH131432)
606606
- Clang now emits a warning when class template argument deduction for alias templates is used in C++17. (#GH133806)
607+
- Fix missing initializer for inline static template member with auto type caused by delayed template instantiation. (#GH138122)
607608

608609
Bug Fixes to AST Handling
609610
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6028,11 +6028,11 @@ void Sema::BuildVariableInstantiation(
60286028
Context.setStaticLocalNumber(NewVar, Context.getStaticLocalNumber(OldVar));
60296029

60306030
// Figure out whether to eagerly instantiate the initializer.
6031-
if (InstantiatingVarTemplate || InstantiatingVarTemplatePartialSpec) {
6032-
// We're producing a template. Don't instantiate the initializer yet.
6033-
} else if (NewVar->getType()->isUndeducedType()) {
6031+
if (NewVar->getType()->isUndeducedType()) {
60346032
// We need the type to complete the declaration of the variable.
60356033
InstantiateVariableInitializer(NewVar, OldVar, TemplateArgs);
6034+
} else if (InstantiatingVarTemplate || InstantiatingVarTemplatePartialSpec) {
6035+
// We're producing a template. Don't instantiate the initializer yet.
60366036
} else if (InstantiatingSpecFromTemplate ||
60376037
(OldVar->isInline() && OldVar->isThisDeclarationADefinition() &&
60386038
!NewVar->isThisDeclarationADefinition())) {

clang/test/CodeGenCXX/cxx1z-inline-variables.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
// RUN: %clang_cc1 -std=c++1z %s -emit-llvm -o - -triple x86_64-linux-gnu | FileCheck %s
22

3+
template <typename T> struct InlineAuto {
4+
template <typename G> inline static auto var = 5;
5+
};
6+
int inlineauto = InlineAuto<int>::var<int>;
7+
// CHECK: @_ZN10InlineAutoIiE3varIiEE = {{.*}}i32 5{{.*}}comdat
8+
//
9+
template <typename> struct PartialInlineAuto {
10+
template <typename, typename> inline static auto var = 6;
11+
template <typename T> inline static auto var<int, T> = 7;
12+
};
13+
14+
int partialinlineauto = PartialInlineAuto<int>::var<int, int>;
15+
// CHECK: @_ZN17PartialInlineAutoIiE3varIiiEE = {{.*}}i32 7{{.*}}comdat
16+
317
struct Q {
418
// CHECK: @_ZN1Q1kE = linkonce_odr constant i32 5, comdat
519
static constexpr int k = 5;

clang/test/SemaTemplate/cxx17-inline-variables.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,15 @@ template <typename T> constexpr int A<T>::n = sizeof(A) + sizeof(T);
2727
template <typename T> inline constexpr int A<T>::m = sizeof(A) + sizeof(T);
2828
static_assert(A<int>().f() == 5);
2929
static_assert(A<int>().g() == 5);
30+
31+
template <typename T> struct InlineAuto {
32+
template <typename G> inline static auto var = 5;
33+
};
34+
35+
template <typename> struct PartialInlineAuto {
36+
template <typename, typename> inline static auto var = 6;
37+
template <typename T> inline static auto var<int, T> = 7;
38+
};
39+
40+
int inlineauto = InlineAuto<int>::var<int>;
41+
int partialinlineauto = PartialInlineAuto<int>::var<int, int>;

clang/tools/driver/driver.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ std::string GetExecutablePath(const char *Argv0, bool CanonicalPrefixes) {
7272

7373
// This just needs to be some symbol in the binary; C++ doesn't
7474
// allow taking the address of ::main however.
75-
void *P = (void*) (intptr_t) GetExecutablePath;
75+
void *P = (void *)(intptr_t)GetExecutablePath;
7676
return llvm::sys::fs::getMainExecutable(Argv0, P);
7777
}
7878

@@ -105,10 +105,10 @@ static void insertTargetAndModeArgs(const ParsedClangName &NameParts,
105105
}
106106

107107
if (NameParts.TargetIsValid) {
108-
const char *arr[] = {"-target", GetStableCStr(SavedStrings,
109-
NameParts.TargetPrefix)};
110-
ArgVector.insert(ArgVector.begin() + InsertionPoint,
111-
std::begin(arr), std::end(arr));
108+
const char *arr[] = {"-target",
109+
GetStableCStr(SavedStrings, NameParts.TargetPrefix)};
110+
ArgVector.insert(ArgVector.begin() + InsertionPoint, std::begin(arr),
111+
std::end(arr));
112112
}
113113
}
114114

@@ -328,8 +328,8 @@ int clang_main(int Argc, char **Argv, const llvm::ToolContext &ToolContext) {
328328
// actions.
329329
DiagOpts->DiagnosticSuppressionMappingsFile.clear();
330330

331-
TextDiagnosticPrinter *DiagClient
332-
= new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts);
331+
TextDiagnosticPrinter *DiagClient =
332+
new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts);
333333
FixupDiagPrefixExeName(DiagClient, ProgName);
334334

335335
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
@@ -439,8 +439,8 @@ int clang_main(int Argc, char **Argv, const llvm::ToolContext &ToolContext) {
439439
if (::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH"))
440440
llvm::dbgs() << llvm::getBugReportMsg();
441441
if (FailingCommand != nullptr &&
442-
TheDriver.maybeGenerateCompilationDiagnostics(CommandStatus, ReproLevel,
443-
*C, *FailingCommand))
442+
TheDriver.maybeGenerateCompilationDiagnostics(CommandStatus, ReproLevel,
443+
*C, *FailingCommand))
444444
Res = 1;
445445

446446
Diags.getClient()->finish();

0 commit comments

Comments
 (0)