diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-10-29 00:04:11 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-10-29 00:04:11 +0000 |
commit | 21610380de972a5307dfb07f446b44fbe2989be5 (patch) | |
tree | 95c3192bec0dc12a820a0f05839d4c2fec861d6d /clang/lib/Sema/SemaTemplateInstantiate.cpp | |
parent | 6c4d255bf3d64fd2ecb48334e780c87f060f1280 (diff) | |
download | bcm5719-llvm-21610380de972a5307dfb07f446b44fbe2989be5.tar.gz bcm5719-llvm-21610380de972a5307dfb07f446b44fbe2989be5.zip |
Implement support for semantic checking and template instantiation of
class template partial specializations of member templates. Also,
fixes a silly little bug in the marking of "used" template parameters
in member templates. Fixes PR5236.
llvm-svn: 85447
Diffstat (limited to 'clang/lib/Sema/SemaTemplateInstantiate.cpp')
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 105 |
1 files changed, 58 insertions, 47 deletions
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 14930134dad..794ec2a9ef9 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -981,61 +981,72 @@ Sema::InstantiateClassTemplateSpecialization( } } - if (Matched.size() == 1) { - // -- If exactly one matching specialization is found, the - // instantiation is generated from that specialization. - Pattern = Matched[0].first; - ClassTemplateSpec->setInstantiationOf(Matched[0].first, Matched[0].second); - } else if (Matched.size() > 1) { - // -- If more than one matching specialization is found, the - // partial order rules (14.5.4.2) are used to determine - // whether one of the specializations is more specialized - // than the others. If none of the specializations is more - // specialized than all of the other matching - // specializations, then the use of the class template is - // ambiguous and the program is ill-formed. + if (Matched.size() >= 1) { llvm::SmallVector<MatchResult, 4>::iterator Best = Matched.begin(); - for (llvm::SmallVector<MatchResult, 4>::iterator P = Best + 1, - PEnd = Matched.end(); - P != PEnd; ++P) { - if (getMoreSpecializedPartialSpecialization(P->first, Best->first) - == P->first) - Best = P; - } - - // Determine if the best partial specialization is more specialized than - // the others. - bool Ambiguous = false; - for (llvm::SmallVector<MatchResult, 4>::iterator P = Matched.begin(), - PEnd = Matched.end(); - P != PEnd; ++P) { - if (P != Best && - getMoreSpecializedPartialSpecialization(P->first, Best->first) - != Best->first) { - Ambiguous = true; - break; + if (Matched.size() == 1) { + // -- If exactly one matching specialization is found, the + // instantiation is generated from that specialization. + // We don't need to do anything for this. + } else { + // -- If more than one matching specialization is found, the + // partial order rules (14.5.4.2) are used to determine + // whether one of the specializations is more specialized + // than the others. If none of the specializations is more + // specialized than all of the other matching + // specializations, then the use of the class template is + // ambiguous and the program is ill-formed. + for (llvm::SmallVector<MatchResult, 4>::iterator P = Best + 1, + PEnd = Matched.end(); + P != PEnd; ++P) { + if (getMoreSpecializedPartialSpecialization(P->first, Best->first) + == P->first) + Best = P; } - } - - if (Ambiguous) { - // Partial ordering did not produce a clear winner. Complain. - ClassTemplateSpec->setInvalidDecl(); - Diag(PointOfInstantiation, diag::err_partial_spec_ordering_ambiguous) - << ClassTemplateSpec; - // Print the matching partial specializations. + // Determine if the best partial specialization is more specialized than + // the others. + bool Ambiguous = false; 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); - - return true; + P != PEnd; ++P) { + if (P != Best && + getMoreSpecializedPartialSpecialization(P->first, Best->first) + != Best->first) { + Ambiguous = true; + break; + } + } + + if (Ambiguous) { + // Partial ordering did not produce a clear winner. Complain. + ClassTemplateSpec->setInvalidDecl(); + Diag(PointOfInstantiation, diag::err_partial_spec_ordering_ambiguous) + << ClassTemplateSpec; + + // Print the matching partial specializations. + 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); + + return true; + } } // Instantiate using the best class template partial specialization. - Pattern = Best->first; + ClassTemplatePartialSpecializationDecl *OrigPartialSpec = Best->first; + while (OrigPartialSpec->getInstantiatedFromMember()) { + // If we've found an explicit specialization of this class template, + // stop here and use that as the pattern. + if (OrigPartialSpec->isMemberSpecialization()) + break; + + OrigPartialSpec = OrigPartialSpec->getInstantiatedFromMember(); + } + + Pattern = OrigPartialSpec; ClassTemplateSpec->setInstantiationOf(Best->first, Best->second); } else { // -- If no matches are found, the instantiation is generated |