summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-10-12 23:32:35 +0000
committerDouglas Gregor <dgregor@apple.com>2010-10-12 23:32:35 +0000
commit5bb5e4ad9d8ed8ac59ae15c716fea9b34a88fd59 (patch)
tree1379ab73184f2e3cd6f60f6d13d7a4e2e2653f98 /clang/lib/Sema
parent67f70aaf5a2a4ab5b3ec0ae672b149d34cc0677f (diff)
downloadbcm5719-llvm-5bb5e4ad9d8ed8ac59ae15c716fea9b34a88fd59.tar.gz
bcm5719-llvm-5bb5e4ad9d8ed8ac59ae15c716fea9b34a88fd59.zip
Introduce support for emitting diagnostics (warnings + their notes)
that are suppressed during template argument deduction. This change queues diagnostics computed during template argument deduction. Then, if the resulting function template specialization or partial specialization is chosen by overload resolution or partial ordering (respectively), we will emit the queued diagnostics at that point. This addresses most of PR6784. However, the check for unnamed/local template arguments (which existed before this change) is still only skin-deep, and needs to be extended to look deeper into types. It must be improved to finish PR6784. llvm-svn: 116373
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/Sema.cpp55
-rw-r--r--clang/lib/Sema/SemaExpr.cpp18
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp6
-rw-r--r--clang/lib/Sema/SemaInit.cpp4
-rw-r--r--clang/lib/Sema/SemaOverload.cpp25
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp3
-rw-r--r--clang/lib/Sema/SemaTemplateDeduction.cpp22
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp55
8 files changed, 131 insertions, 57 deletions
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index a0046a2caa1..1b3572a6498 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -19,6 +19,7 @@
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/APFloat.h"
#include "clang/Sema/CXXFieldCollector.h"
+#include "clang/Sema/TemplateDeduction.h"
#include "clang/Sema/ExternalSemaSource.h"
#include "clang/Sema/ObjCMethodList.h"
#include "clang/Sema/PrettyDeclStackTrace.h"
@@ -433,6 +434,41 @@ NamedDecl *Sema::getCurFunctionOrMethodDecl() {
}
Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() {
+ if (!isActive())
+ return;
+
+ if (TemplateDeductionInfo *Info = SemaRef.isSFINAEContext()) {
+ switch (Diagnostic::getDiagnosticSFINAEResponse(getDiagID())) {
+ case Diagnostic::SFINAE_Report:
+ // Fall through; we'll report the diagnostic below.
+ break;
+
+ case Diagnostic::SFINAE_SubstitutionFailure:
+ // Count this failure so that we know that template argument deduction
+ // has failed.
+ ++SemaRef.NumSFINAEErrors;
+ SemaRef.Diags.setLastDiagnosticIgnored();
+ SemaRef.Diags.Clear();
+ Clear();
+ return;
+
+ case Diagnostic::SFINAE_Suppress:
+ // Make a copy of this suppressed diagnostic and store it with the
+ // template-deduction information;
+ DiagnosticInfo DiagInfo(&SemaRef.Diags);
+ Info->addSuppressedDiagnostic(DiagInfo.getLocation(),
+ PartialDiagnostic(DiagInfo,
+ SemaRef.Context.getDiagAllocator()));
+
+ // Suppress this diagnostic.
+ SemaRef.Diags.setLastDiagnosticIgnored();
+ SemaRef.Diags.Clear();
+ Clear();
+ return;
+ }
+ }
+
+ // Emit the diagnostic.
if (!this->Emit())
return;
@@ -451,25 +487,6 @@ Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() {
}
Sema::SemaDiagnosticBuilder Sema::Diag(SourceLocation Loc, unsigned DiagID) {
- if (isSFINAEContext()) {
- switch (Diagnostic::getDiagnosticSFINAEResponse(DiagID)) {
- case Diagnostic::SFINAE_Report:
- // Fall through; we'll report the diagnostic below.
- break;
-
- case Diagnostic::SFINAE_SubstitutionFailure:
- // Count this failure so that we know that template argument deduction
- // has failed.
- ++NumSFINAEErrors;
- // Fall through
-
- case Diagnostic::SFINAE_Suppress:
- // Suppress this diagnostic.
- Diags.setLastDiagnosticIgnored();
- return SemaDiagnosticBuilder(*this);
- }
- }
-
DiagnosticBuilder DB = Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID);
return SemaDiagnosticBuilder(DB, *this, DiagID);
}
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 68bb2b07233..609465c5052 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -56,6 +56,24 @@ using namespace sema;
/// referenced), false otherwise.
///
bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) {
+ if (getLangOptions().CPlusPlus && isa<FunctionDecl>(D)) {
+ // If there were any diagnostics suppressed by template argument deduction,
+ // emit them now.
+ llvm::DenseMap<Decl *, llvm::SmallVector<PartialDiagnosticAt, 1> >::iterator
+ Pos = SuppressedDiagnostics.find(D->getCanonicalDecl());
+ if (Pos != SuppressedDiagnostics.end()) {
+ llvm::SmallVectorImpl<PartialDiagnosticAt> &Suppressed = Pos->second;
+ for (unsigned I = 0, N = Suppressed.size(); I != N; ++I)
+ Diag(Suppressed[I].first, Suppressed[I].second);
+
+ // Clear out the list of suppressed diagnostics, so that we don't emit
+ // them again for this specialization. However, we don't remove this
+ // entry from the table, because we want to avoid ever emitting these
+ // diagnostics again.
+ Suppressed.clear();
+ }
+ }
+
// See if the decl is deprecated.
if (const DeprecatedAttr *DA = D->getAttr<DeprecatedAttr>())
EmitDeprecationWarning(D, DA->getMessage(), Loc);
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 04c15e3f001..00a3e27edc9 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -1551,9 +1551,11 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
return ExprError();
if (!RD->hasTrivialDestructor())
- if (const CXXDestructorDecl *Dtor = LookupDestructor(RD))
+ if (CXXDestructorDecl *Dtor = LookupDestructor(RD)) {
MarkDeclarationReferenced(StartLoc,
const_cast<CXXDestructorDecl*>(Dtor));
+ DiagnoseUseOfDecl(Dtor, StartLoc);
+ }
}
if (!OperatorDelete) {
@@ -1829,7 +1831,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
if (DiagnoseUseOfDecl(Fn, From->getSourceRange().getBegin()))
return true;
-
+
From = FixOverloadedFunctionReference(From, Found, Fn);
FromType = From->getType();
}
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 7f0f2767c64..1e48930f972 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -3765,6 +3765,7 @@ InitializationSequence::Perform(Sema &S,
S.CheckDestructorAccess(CurInitExpr->getLocStart(), Destructor,
S.PDiag(diag::err_access_dtor_temp) << T);
S.MarkDeclarationReferenced(CurInitExpr->getLocStart(), Destructor);
+ S.DiagnoseUseOfDecl(Destructor, CurInitExpr->getLocStart());
}
}
@@ -3858,7 +3859,8 @@ InitializationSequence::Perform(Sema &S,
unsigned NumExprs = ConstructorArgs.size();
Expr **Exprs = (Expr **)ConstructorArgs.take();
S.MarkDeclarationReferenced(Loc, Constructor);
-
+ S.DiagnoseUseOfDecl(Constructor, Loc);
+
TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo();
if (!TSInfo)
TSInfo = S.Context.getTrivialTypeSourceInfo(Entity.getType(), Loc);
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 1437238f3bf..078669a556a 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -5489,6 +5489,7 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
// placement new (5.3.4), as well as non-default initialization (8.5).
if (Best->Function)
S.MarkDeclarationReferenced(Loc, Best->Function);
+
return OR_Success;
}
@@ -6313,7 +6314,7 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
// whose type matches exactly.
llvm::SmallVector<std::pair<DeclAccessPair, FunctionDecl*>, 4> Matches;
llvm::SmallVector<FunctionDecl *, 4> NonMatches;
-
+
bool FoundNonTemplateFunction = false;
for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
E = OvlExpr->decls_end(); I != E; ++I) {
@@ -6344,7 +6345,6 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
// resulting template argument list is used to generate a single
// function template specialization, which is added to the set of
// overloaded functions considered.
- // FIXME: We don't really want to build the specialization here, do we?
FunctionDecl *Specialization = 0;
TemplateDeductionInfo Info(Context, OvlExpr->getNameLoc());
if (TemplateDeductionResult Result
@@ -6355,10 +6355,10 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
} else {
// Template argument deduction ensures that we have an exact match.
// This function template specicalization works.
+ Specialization = cast<FunctionDecl>(Specialization->getCanonicalDecl());
assert(FunctionType
== Context.getCanonicalType(Specialization->getType()));
- Matches.push_back(std::make_pair(I.getPair(),
- cast<FunctionDecl>(Specialization->getCanonicalDecl())));
+ Matches.push_back(std::make_pair(I.getPair(), Specialization));
}
continue;
@@ -6403,10 +6403,11 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
return 0;
} else if (Matches.size() == 1) {
FunctionDecl *Result = Matches[0].second;
- FoundResult = Matches[0].first;
+ FoundResult = Matches[0].first;
MarkDeclarationReferenced(From->getLocStart(), Result);
- if (Complain)
+ if (Complain) {
CheckAddressOfMemberAccess(OvlExpr, Matches[0].first);
+ }
return Result;
}
@@ -6441,10 +6442,8 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
MarkDeclarationReferenced(From->getLocStart(), *Result);
FoundResult = Matches[Result - MatchesCopy.begin()].first;
- if (Complain) {
+ if (Complain)
CheckUnresolvedAccess(*this, OvlExpr, FoundResult);
- DiagnoseUseOfDecl(FoundResult, OvlExpr->getNameLoc());
- }
return cast<FunctionDecl>(*Result);
}
@@ -6464,10 +6463,8 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
if (Matches.size() == 1) {
MarkDeclarationReferenced(From->getLocStart(), Matches[0].second);
FoundResult = Matches[0].first;
- if (Complain) {
+ if (Complain)
CheckUnresolvedAccess(*this, OvlExpr, Matches[0].first);
- DiagnoseUseOfDecl(Matches[0].first, OvlExpr->getNameLoc());
- }
return cast<FunctionDecl>(Matches[0].second);
}
@@ -6543,7 +6540,7 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From) {
Matched = Specialization;
}
-
+
return Matched;
}
@@ -6734,7 +6731,7 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
case OR_Success: {
FunctionDecl *FDecl = Best->Function;
CheckUnresolvedLookupAccess(ULE, Best->FoundDecl);
- DiagnoseUseOfDecl(Best->FoundDecl, ULE->getNameLoc());
+ DiagnoseUseOfDecl(FDecl? FDecl : Best->FoundDecl, ULE->getNameLoc());
Fn = FixOverloadedFunctionReference(Fn, Best->FoundDecl, FDecl);
return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, RParenLoc);
}
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index ec928ea4b7b..a569a966fa3 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -2363,6 +2363,9 @@ bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param,
// template-argument for a template type-parameter.
// C++0x allows these, and even in C++03 we allow them as an extension with
// a warning.
+ //
+ // FIXME: We're not handling the "type compounded from any of these types"
+ // case.
SourceRange SR = ArgInfo->getTypeLoc().getSourceRange();
if (!LangOpts.CPlusPlus0x) {
const TagType *Tag = 0;
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index ce3748b901a..ae9052b704a 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -1127,7 +1127,7 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
return Result;
InstantiatingTemplate Inst(*this, Partial->getLocation(), Partial,
- Deduced.data(), Deduced.size());
+ Deduced.data(), Deduced.size(), Info);
if (Inst)
return TDK_InstantiationDepth;
@@ -1214,7 +1214,8 @@ Sema::SubstituteExplicitTemplateArguments(
// and then substitute them into the function parameter types.
InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(),
FunctionTemplate, Deduced.data(), Deduced.size(),
- ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution);
+ ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution,
+ Info);
if (Inst)
return TDK_InstantiationDepth;
@@ -1374,7 +1375,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
// actual function declaration.
InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(),
FunctionTemplate, Deduced.data(), Deduced.size(),
- ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution);
+ ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution,
+ Info);
if (Inst)
return TDK_InstantiationDepth;
@@ -1429,7 +1431,7 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
TemplateArgumentLoc Arg = getTrivialTemplateArgumentLoc(*this,
Deduced[I],
NTTPType,
- SourceLocation());
+ Info.getLocation());
// Check the template argument, converting it as necessary.
if (CheckTemplateArgument(Param, Arg,
@@ -1515,6 +1517,18 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
return TDK_SubstitutionFailure;
}
+ // If we suppressed any diagnostics while performing template argument
+ // deduction, and if we haven't already instantiated this declaration,
+ // keep track of these diagnostics. They'll be emitted if this specialization
+ // is actually used.
+ if (Info.diag_begin() != Info.diag_end()) {
+ llvm::DenseMap<Decl *, llvm::SmallVector<PartialDiagnosticAt, 1> >::iterator
+ Pos = SuppressedDiagnostics.find(Specialization->getCanonicalDecl());
+ if (Pos == SuppressedDiagnostics.end())
+ SuppressedDiagnostics[Specialization->getCanonicalDecl()]
+ .append(Info.diag_begin(), Info.diag_end());
+ }
+
return TDK_Success;
}
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 98b8ccd8d85..2bc0e40b39a 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -148,7 +148,6 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
Decl *Entity,
SourceRange InstantiationRange)
: SemaRef(SemaRef) {
-
Invalid = CheckInstantiationDepth(PointOfInstantiation,
InstantiationRange);
if (!Invalid) {
@@ -192,6 +191,7 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs,
ActiveTemplateInstantiation::InstantiationKind Kind,
+ sema::TemplateDeductionInfo &DeductionInfo,
SourceRange InstantiationRange)
: SemaRef(SemaRef) {
@@ -204,6 +204,7 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
Inst.Entity = reinterpret_cast<uintptr_t>(FunctionTemplate);
Inst.TemplateArgs = TemplateArgs;
Inst.NumTemplateArgs = NumTemplateArgs;
+ Inst.DeductionInfo = &DeductionInfo;
Inst.InstantiationRange = InstantiationRange;
SemaRef.ActiveTemplateInstantiations.push_back(Inst);
@@ -217,6 +218,7 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
ClassTemplatePartialSpecializationDecl *PartialSpec,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs,
+ sema::TemplateDeductionInfo &DeductionInfo,
SourceRange InstantiationRange)
: SemaRef(SemaRef) {
@@ -228,6 +230,7 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
Inst.Entity = reinterpret_cast<uintptr_t>(PartialSpec);
Inst.TemplateArgs = TemplateArgs;
Inst.NumTemplateArgs = NumTemplateArgs;
+ Inst.DeductionInfo = &DeductionInfo;
Inst.InstantiationRange = InstantiationRange;
SemaRef.ActiveTemplateInstantiations.push_back(Inst);
@@ -516,7 +519,7 @@ void Sema::PrintInstantiationStack() {
}
}
-bool Sema::isSFINAEContext() const {
+TemplateDeductionInfo *Sema::isSFINAEContext() const {
using llvm::SmallVector;
for (SmallVector<ActiveTemplateInstantiation, 16>::const_reverse_iterator
Active = ActiveTemplateInstantiations.rbegin(),
@@ -528,7 +531,7 @@ bool Sema::isSFINAEContext() const {
case ActiveTemplateInstantiation::TemplateInstantiation:
case ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation:
// This is a template instantiation, so there is no SFINAE.
- return false;
+ return 0;
case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation:
case ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution:
@@ -542,11 +545,12 @@ bool Sema::isSFINAEContext() const {
case ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution:
// We're either substitution explicitly-specified template arguments
// or deduced template arguments, so SFINAE applies.
- return true;
+ assert(Active->DeductionInfo && "Missing deduction info pointer");
+ return Active->DeductionInfo;
}
}
- return false;
+ return 0;
}
//===----------------------------------------------------------------------===/
@@ -1255,6 +1259,16 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
return Invalid;
}
+namespace {
+ /// \brief A partial specialization whose template arguments have matched
+ /// a given template-id.
+ struct PartialSpecMatchResult {
+ ClassTemplatePartialSpecializationDecl *Partial;
+ TemplateArgumentList *Args;
+ llvm::SmallVector<PartialDiagnosticAt, 1> Diagnostics;
+ };
+}
+
bool
Sema::InstantiateClassTemplateSpecialization(
SourceLocation PointOfInstantiation,
@@ -1304,8 +1318,7 @@ Sema::InstantiateClassTemplateSpecialization(
// matching the template arguments of the class template
// specialization with the template argument lists of the partial
// specializations.
- typedef std::pair<ClassTemplatePartialSpecializationDecl *,
- TemplateArgumentList *> MatchResult;
+ typedef PartialSpecMatchResult MatchResult;
llvm::SmallVector<MatchResult, 4> Matched;
llvm::SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
Template->getPartialSpecializations(PartialSpecs);
@@ -1320,7 +1333,10 @@ Sema::InstantiateClassTemplateSpecialization(
// diagnostics, later.
(void)Result;
} else {
- Matched.push_back(std::make_pair(Partial, Info.take()));
+ Matched.push_back(PartialSpecMatchResult());
+ Matched.back().Partial = Partial;
+ Matched.back().Args = Info.take();
+ Matched.back().Diagnostics.append(Info.diag_begin(), Info.diag_end());
}
}
@@ -1341,9 +1357,9 @@ Sema::InstantiateClassTemplateSpecialization(
for (llvm::SmallVector<MatchResult, 4>::iterator P = Best + 1,
PEnd = Matched.end();
P != PEnd; ++P) {
- if (getMoreSpecializedPartialSpecialization(P->first, Best->first,
+ if (getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial,
PointOfInstantiation)
- == P->first)
+ == P->Partial)
Best = P;
}
@@ -1354,9 +1370,9 @@ Sema::InstantiateClassTemplateSpecialization(
PEnd = Matched.end();
P != PEnd; ++P) {
if (P != Best &&
- getMoreSpecializedPartialSpecialization(P->first, Best->first,
+ getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial,
PointOfInstantiation)
- != Best->first) {
+ != Best->Partial) {
Ambiguous = true;
break;
}
@@ -1372,16 +1388,17 @@ Sema::InstantiateClassTemplateSpecialization(
for (llvm::SmallVector<MatchResult, 4>::iterator P = Matched.begin(),
PEnd = Matched.end();
P != PEnd; ++P)
- Diag(P->first->getLocation(), diag::note_partial_spec_match)
- << getTemplateArgumentBindingsText(P->first->getTemplateParameters(),
- *P->second);
+ Diag(P->Partial->getLocation(), diag::note_partial_spec_match)
+ << getTemplateArgumentBindingsText(
+ P->Partial->getTemplateParameters(),
+ *P->Args);
return true;
}
}
// Instantiate using the best class template partial specialization.
- ClassTemplatePartialSpecializationDecl *OrigPartialSpec = Best->first;
+ ClassTemplatePartialSpecializationDecl *OrigPartialSpec = Best->Partial;
while (OrigPartialSpec->getInstantiatedFromMember()) {
// If we've found an explicit specialization of this class template,
// stop here and use that as the pattern.
@@ -1392,7 +1409,11 @@ Sema::InstantiateClassTemplateSpecialization(
}
Pattern = OrigPartialSpec;
- ClassTemplateSpec->setInstantiationOf(Best->first, Best->second);
+ ClassTemplateSpec->setInstantiationOf(Best->Partial, Best->Args);
+
+ // Report any suppressed diagnostics.
+ for (unsigned I = 0, N = Best->Diagnostics.size(); I != N; ++I)
+ Diag(Best->Diagnostics[I].first, Best->Diagnostics[I].second);
} else {
// -- If no matches are found, the instantiation is generated
// from the primary template.
OpenPOWER on IntegriCloud