mirror of https://github.com/microsoft/clang.git
[modules] When loading a template specialization, re-canonicalize its template
arguments because the reloaded form might have become non-canonical across the serialization/deserialization step (this particularly happens when the canonical form of the type involves an expression). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@244409 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
14d62ae679
commit
47ba20a775
|
@ -1927,8 +1927,9 @@ public:
|
|||
unsigned &Idx);
|
||||
|
||||
/// \brief Read a template argument.
|
||||
TemplateArgument ReadTemplateArgument(ModuleFile &F,
|
||||
const RecordData &Record,unsigned &Idx);
|
||||
TemplateArgument ReadTemplateArgument(ModuleFile &F, const RecordData &Record,
|
||||
unsigned &Idx,
|
||||
bool Canonicalize = false);
|
||||
|
||||
/// \brief Read a template parameter list.
|
||||
TemplateParameterList *ReadTemplateParameterList(ModuleFile &F,
|
||||
|
@ -1936,10 +1937,9 @@ public:
|
|||
unsigned &Idx);
|
||||
|
||||
/// \brief Read a template argument array.
|
||||
void
|
||||
ReadTemplateArgumentList(SmallVectorImpl<TemplateArgument> &TemplArgs,
|
||||
ModuleFile &F, const RecordData &Record,
|
||||
unsigned &Idx);
|
||||
void ReadTemplateArgumentList(SmallVectorImpl<TemplateArgument> &TemplArgs,
|
||||
ModuleFile &F, const RecordData &Record,
|
||||
unsigned &Idx, bool Canonicalize = false);
|
||||
|
||||
/// \brief Read a UnresolvedSet structure.
|
||||
void ReadUnresolvedSet(ModuleFile &F, LazyASTUnresolvedSet &Set,
|
||||
|
|
|
@ -7568,9 +7568,19 @@ ASTReader::ReadTemplateName(ModuleFile &F, const RecordData &Record,
|
|||
llvm_unreachable("Unhandled template name kind!");
|
||||
}
|
||||
|
||||
TemplateArgument
|
||||
ASTReader::ReadTemplateArgument(ModuleFile &F,
|
||||
const RecordData &Record, unsigned &Idx) {
|
||||
TemplateArgument ASTReader::ReadTemplateArgument(ModuleFile &F,
|
||||
const RecordData &Record,
|
||||
unsigned &Idx,
|
||||
bool Canonicalize) {
|
||||
if (Canonicalize) {
|
||||
// The caller wants a canonical template argument. Sometimes the AST only
|
||||
// wants template arguments in canonical form (particularly as the template
|
||||
// argument lists of template specializations) so ensure we preserve that
|
||||
// canonical form across serialization.
|
||||
TemplateArgument Arg = ReadTemplateArgument(F, Record, Idx, false);
|
||||
return Context.getCanonicalTemplateArgument(Arg);
|
||||
}
|
||||
|
||||
TemplateArgument::ArgKind Kind = (TemplateArgument::ArgKind)Record[Idx++];
|
||||
switch (Kind) {
|
||||
case TemplateArgument::Null:
|
||||
|
@ -7634,11 +7644,11 @@ void
|
|||
ASTReader::
|
||||
ReadTemplateArgumentList(SmallVectorImpl<TemplateArgument> &TemplArgs,
|
||||
ModuleFile &F, const RecordData &Record,
|
||||
unsigned &Idx) {
|
||||
unsigned &Idx, bool Canonicalize) {
|
||||
unsigned NumTemplateArgs = Record[Idx++];
|
||||
TemplArgs.reserve(NumTemplateArgs);
|
||||
while (NumTemplateArgs--)
|
||||
TemplArgs.push_back(ReadTemplateArgument(F, Record, Idx));
|
||||
TemplArgs.push_back(ReadTemplateArgument(F, Record, Idx, Canonicalize));
|
||||
}
|
||||
|
||||
/// \brief Read a UnresolvedSet structure.
|
||||
|
|
|
@ -779,8 +779,9 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
|
|||
|
||||
// Template arguments.
|
||||
SmallVector<TemplateArgument, 8> TemplArgs;
|
||||
Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx);
|
||||
|
||||
Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx,
|
||||
/*Canonicalize*/ true);
|
||||
|
||||
// Template args as written.
|
||||
SmallVector<TemplateArgumentLoc, 8> TemplArgLocs;
|
||||
SourceLocation LAngleLoc, RAngleLoc;
|
||||
|
@ -1937,7 +1938,8 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
|
|||
}
|
||||
|
||||
SmallVector<TemplateArgument, 8> TemplArgs;
|
||||
Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx);
|
||||
Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx,
|
||||
/*Canonicalize*/ true);
|
||||
D->TemplateArgs = TemplateArgumentList::CreateCopy(C, TemplArgs.data(),
|
||||
TemplArgs.size());
|
||||
D->PointOfInstantiation = ReadSourceLocation(Record, Idx);
|
||||
|
@ -2064,7 +2066,8 @@ ASTDeclReader::VisitVarTemplateSpecializationDeclImpl(
|
|||
}
|
||||
|
||||
SmallVector<TemplateArgument, 8> TemplArgs;
|
||||
Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx);
|
||||
Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx,
|
||||
/*Canonicalize*/ true);
|
||||
D->TemplateArgs =
|
||||
TemplateArgumentList::CreateCopy(C, TemplArgs.data(), TemplArgs.size());
|
||||
D->PointOfInstantiation = ReadSourceLocation(Record, Idx);
|
||||
|
|
|
@ -9,6 +9,10 @@
|
|||
//#pragma weak pragma_weak01 // expected-warning {{weak identifier 'pragma_weak01' never declared}}
|
||||
//#pragma weak pragma_weak04 // expected-warning {{weak identifier 'pragma_waek04' never declared}}
|
||||
|
||||
#ifdef MERGE_NO_REEXPORT
|
||||
#include "merge_no_reexport.h"
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
#include "m00.h"
|
||||
#include "m01.h"
|
||||
|
|
|
@ -3,4 +3,5 @@ module m01 { header "Inputs/stress1/m01.h" export * }
|
|||
module m02 { header "Inputs/stress1/m02.h" export * }
|
||||
module m03 { header "Inputs/stress1/m03.h" export * }
|
||||
|
||||
module merge_no_reexport { header "Inputs/stress1/merge_no_reexport.h" }
|
||||
module merge00 { header "Inputs/stress1/merge00.h" export * }
|
||||
|
|
|
@ -111,3 +111,16 @@ namespace Anon {
|
|||
};
|
||||
};
|
||||
}
|
||||
|
||||
namespace ClassTemplatePartialSpec {
|
||||
template<typename T> struct F;
|
||||
template<template<int> class A, int B> struct F<A<B>> {
|
||||
template<typename C> F();
|
||||
};
|
||||
template<template<int> class A, int B> template<typename C> F<A<B>>::F() {}
|
||||
|
||||
template<typename A, int B> struct F<A[B]> {
|
||||
template<typename C> F();
|
||||
};
|
||||
template<typename A, int B> template<typename C> F<A[B]>::F() {}
|
||||
}
|
||||
|
|
|
@ -107,6 +107,18 @@
|
|||
//
|
||||
// RUN: diff -u %t/stress1.ll %t/stress1_check.ll
|
||||
//
|
||||
// RUN: %clang_cc1 -fmodules -x c++ -std=c++11 \
|
||||
// RUN: -I Inputs/stress1 \
|
||||
// RUN: -fmodules-cache-path=%t \
|
||||
// RUN: -fmodule-map-file-home-is-cwd \
|
||||
// RUN: -fmodule-file=%t/m00.pcm \
|
||||
// RUN: -fmodule-file=%t/m01.pcm \
|
||||
// RUN: -fmodule-file=%t/m02.pcm \
|
||||
// RUN: -fmodule-file=%t/m03.pcm \
|
||||
// RUN: -emit-module -fmodule-name=merge00 -o /dev/null \
|
||||
// RUN: -DMERGE_NO_REEXPORT \
|
||||
// RUN: Inputs/stress1/module.modulemap
|
||||
//
|
||||
// expected-no-diagnostics
|
||||
|
||||
#include "m00.h"
|
||||
|
|
Loading…
Reference in New Issue