aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaTemplate.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2011-07-17 15:40:56 +0000
committerDimitry Andric <dim@FreeBSD.org>2011-07-17 15:40:56 +0000
commit180abc3db9ae3b4fc63cd65b15697e6ffcc8a657 (patch)
tree2097d084eb235c0b12c0bff3445f4ec7bbaa8a12 /lib/Sema/SemaTemplate.cpp
parent29cafa66ad3878dbb9f82615f19fa0bded2e443c (diff)
downloadsrc-180abc3db9ae3b4fc63cd65b15697e6ffcc8a657.tar.gz
src-180abc3db9ae3b4fc63cd65b15697e6ffcc8a657.zip
Notes
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r--lib/Sema/SemaTemplate.cpp134
1 files changed, 77 insertions, 57 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 5d4caacd8124..3ac190e1d4c8 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -294,26 +294,31 @@ void Sema::LookupTemplateName(LookupResult &Found,
if (Found.empty() && !isDependent) {
// If we did not find any names, attempt to correct any typos.
DeclarationName Name = Found.getLookupName();
- if (DeclarationName Corrected = CorrectTypo(Found, S, &SS, LookupCtx,
- false, CTC_CXXCasts)) {
+ Found.clear();
+ if (TypoCorrection Corrected = CorrectTypo(Found.getLookupNameInfo(),
+ Found.getLookupKind(), S, &SS,
+ LookupCtx, false,
+ CTC_CXXCasts)) {
+ Found.setLookupName(Corrected.getCorrection());
+ if (Corrected.getCorrectionDecl())
+ Found.addDecl(Corrected.getCorrectionDecl());
FilterAcceptableTemplateNames(Found);
if (!Found.empty()) {
+ std::string CorrectedStr(Corrected.getAsString(getLangOptions()));
+ std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions()));
if (LookupCtx)
Diag(Found.getNameLoc(), diag::err_no_member_template_suggest)
- << Name << LookupCtx << Found.getLookupName() << SS.getRange()
- << FixItHint::CreateReplacement(Found.getNameLoc(),
- Found.getLookupName().getAsString());
+ << Name << LookupCtx << CorrectedQuotedStr << SS.getRange()
+ << FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr);
else
Diag(Found.getNameLoc(), diag::err_no_template_suggest)
- << Name << Found.getLookupName()
- << FixItHint::CreateReplacement(Found.getNameLoc(),
- Found.getLookupName().getAsString());
+ << Name << CorrectedQuotedStr
+ << FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr);
if (TemplateDecl *Template = Found.getAsSingle<TemplateDecl>())
Diag(Template->getLocation(), diag::note_previous_decl)
- << Template->getDeclName();
+ << CorrectedQuotedStr;
}
} else {
- Found.clear();
Found.setLookupName(Name);
}
}
@@ -1856,7 +1861,8 @@ void Sema::NoteAllFoundTemplates(TemplateName Name) {
QualType Sema::CheckTemplateIdType(TemplateName Name,
SourceLocation TemplateLoc,
TemplateArgumentListInfo &TemplateArgs) {
- DependentTemplateName *DTN = Name.getAsDependentTemplateName();
+ DependentTemplateName *DTN
+ = Name.getUnderlying().getAsDependentTemplateName();
if (DTN && DTN->isIdentifier())
// When building a template-id where the template-name is dependent,
// assume the template is a type template. Either our assumption is
@@ -1892,6 +1898,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
QualType CanonType;
+ bool InstantiationDependent = false;
if (TypeAliasTemplateDecl *AliasTemplate
= dyn_cast<TypeAliasTemplateDecl>(Template)) {
// Find the canonical type for this type alias template specialization.
@@ -1917,7 +1924,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
return QualType();
} else if (Name.isDependent() ||
TemplateSpecializationType::anyDependentTemplateArguments(
- TemplateArgs)) {
+ TemplateArgs, InstantiationDependent)) {
// This class template specialization is a dependent
// type. Therefore, its canonical type is another class template
// specialization type that contains all of the converted
@@ -2357,8 +2364,20 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
return true;
// Add the converted template type argument.
- Converted.push_back(
- TemplateArgument(Context.getCanonicalType(Arg.getAsType())));
+ QualType ArgType = Context.getCanonicalType(Arg.getAsType());
+
+ // Objective-C ARC:
+ // If an explicitly-specified template argument type is a lifetime type
+ // with no lifetime qualifier, the __strong lifetime qualifier is inferred.
+ if (getLangOptions().ObjCAutoRefCount &&
+ ArgType->isObjCLifetimeType() &&
+ !ArgType.getObjCLifetime()) {
+ Qualifiers Qs;
+ Qs.setObjCLifetime(Qualifiers::OCL_Strong);
+ ArgType = Context.getQualifiedType(ArgType, Qs);
+ }
+
+ Converted.push_back(TemplateArgument(ArgType));
return false;
}
@@ -2912,16 +2931,6 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
// arguments, just break out now and we'll fill in the argument pack below.
if ((*Param)->isTemplateParameterPack())
break;
-
- // If our template is a template template parameter that hasn't acquired
- // its proper context yet (e.g., because we're using the template template
- // parameter in the signature of a function template, before we've built
- // the function template itself), don't attempt substitution of default
- // template arguments at this point: we don't have enough context to
- // do it properly.
- if (isTemplateTemplateParameter &&
- Template->getDeclContext()->isTranslationUnit())
- break;
// We have a default template argument that we will use.
TemplateArgumentLoc Arg;
@@ -3307,8 +3316,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
QualType ArgType = Arg->getType();
// See through any implicit casts we added to fix the type.
- while (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(Arg))
- Arg = Cast->getSubExpr();
+ Arg = Arg->IgnoreImpCasts();
// C++ [temp.arg.nontype]p1:
//
@@ -3321,7 +3329,6 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
// expressed as & id-expression where the & is optional if
// the name refers to a function or array, or if the
// corresponding template-parameter is a reference; or
- DeclRefExpr *DRE = 0;
// In C++98/03 mode, give an extension warning on any extra parentheses.
// See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#773
@@ -3337,29 +3344,30 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
Arg = Parens->getSubExpr();
}
+ while (SubstNonTypeTemplateParmExpr *subst =
+ dyn_cast<SubstNonTypeTemplateParmExpr>(Arg))
+ Arg = subst->getReplacement()->IgnoreImpCasts();
+
bool AddressTaken = false;
SourceLocation AddrOpLoc;
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) {
if (UnOp->getOpcode() == UO_AddrOf) {
- // Support &__uuidof(class_with_uuid) as a non-type template argument.
- // Very common in Microsoft COM headers.
- if (S.getLangOptions().Microsoft &&
- isa<CXXUuidofExpr>(UnOp->getSubExpr())) {
- Converted = TemplateArgument(ArgIn);
- return false;
- }
-
- DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr());
+ Arg = UnOp->getSubExpr();
AddressTaken = true;
AddrOpLoc = UnOp->getOperatorLoc();
}
- } else {
- if (S.getLangOptions().Microsoft && isa<CXXUuidofExpr>(Arg)) {
- Converted = TemplateArgument(ArgIn);
- return false;
- }
- DRE = dyn_cast<DeclRefExpr>(Arg);
}
+
+ if (S.getLangOptions().Microsoft && isa<CXXUuidofExpr>(Arg)) {
+ Converted = TemplateArgument(ArgIn);
+ return false;
+ }
+
+ while (SubstNonTypeTemplateParmExpr *subst =
+ dyn_cast<SubstNonTypeTemplateParmExpr>(Arg))
+ Arg = subst->getReplacement()->IgnoreImpCasts();
+
+ DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arg);
if (!DRE) {
S.Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref)
<< Arg->getSourceRange();
@@ -3513,9 +3521,11 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
return true;
}
+ bool ObjCLifetimeConversion;
if (ParamType->isPointerType() &&
!ParamType->getAs<PointerType>()->getPointeeType()->isFunctionType() &&
- S.IsQualificationConversion(ArgType, ParamType, false)) {
+ S.IsQualificationConversion(ArgType, ParamType, false,
+ ObjCLifetimeConversion)) {
// For pointer-to-object types, qualification conversions are
// permitted.
} else {
@@ -3552,10 +3562,10 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
// We can't perform this conversion or binding.
if (ParamType->isReferenceType())
S.Diag(Arg->getLocStart(), diag::err_template_arg_no_ref_bind)
- << ParamType << Arg->getType() << Arg->getSourceRange();
+ << ParamType << ArgIn->getType() << Arg->getSourceRange();
else
S.Diag(Arg->getLocStart(), diag::err_template_arg_not_convertible)
- << Arg->getType() << ParamType << Arg->getSourceRange();
+ << ArgIn->getType() << ParamType << Arg->getSourceRange();
S.Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
@@ -3599,6 +3609,10 @@ bool Sema::CheckTemplateArgumentPointerToMember(Expr *Arg,
Arg = Parens->getSubExpr();
}
+ while (SubstNonTypeTemplateParmExpr *subst =
+ dyn_cast<SubstNonTypeTemplateParmExpr>(Arg))
+ Arg = subst->getReplacement()->IgnoreImpCasts();
+
// A pointer-to-member constant written &Class::member.
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) {
if (UnOp->getOpcode() == UO_AddrOf) {
@@ -3875,8 +3889,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
return Owned(Arg);
}
+ bool ObjCLifetimeConversion;
if (IsQualificationConversion(ArgType, ParamType.getNonReferenceType(),
- false)) {
+ false, ObjCLifetimeConversion)) {
Arg = ImpCastExprToType(Arg, ParamType, CK_NoOp, CastCategory(Arg)).take();
} else if (!Context.hasSameUnqualifiedType(ArgType,
ParamType.getNonReferenceType())) {
@@ -3943,9 +3958,11 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// member, qualification conversions (4.4) are applied.
assert(ParamType->isMemberPointerType() && "Only pointers to members remain");
+ bool ObjCLifetimeConversion;
if (Context.hasSameUnqualifiedType(ParamType, ArgType)) {
// Types match exactly: nothing more to do here.
- } else if (IsQualificationConversion(ArgType, ParamType, false)) {
+ } else if (IsQualificationConversion(ArgType, ParamType, false,
+ ObjCLifetimeConversion)) {
Arg = ImpCastExprToType(Arg, ParamType, CK_NoOp, CastCategory(Arg)).take();
} else {
// We can't perform this conversion.
@@ -4053,8 +4070,10 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
// We might need to perform a trailing qualification conversion, since
// the element type on the parameter could be more qualified than the
// element type in the expression we constructed.
+ bool ObjCLifetimeConversion;
if (IsQualificationConversion(((Expr*) RefExpr.get())->getType(),
- ParamType.getUnqualifiedType(), false))
+ ParamType.getUnqualifiedType(), false,
+ ObjCLifetimeConversion))
RefExpr = ImpCastExprToType(RefExpr.take(), ParamType.getUnqualifiedType(), CK_NoOp);
assert(!RefExpr.isInvalid() &&
@@ -4818,10 +4837,12 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
Converted))
return true;
+ bool InstantiationDependent;
if (!Name.isDependent() &&
!TemplateSpecializationType::anyDependentTemplateArguments(
TemplateArgs.getArgumentArray(),
- TemplateArgs.size())) {
+ TemplateArgs.size(),
+ InstantiationDependent)) {
Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized)
<< ClassTemplate->getDeclName();
isPartialSpecialization = false;
@@ -5346,7 +5367,7 @@ Sema::CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD,
/// explicitly provided as in, e.g., \c void sort<>(char*, char*);
/// as it anyway contains info on the angle brackets locations.
///
-/// \param PrevDecl the set of declarations that may be specialized by
+/// \param Previous the set of declarations that may be specialized by
/// this function specialization.
bool
Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
@@ -5410,13 +5431,12 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
FunctionTemplateSpecializationInfo *SpecInfo
= Specialization->getTemplateSpecializationInfo();
assert(SpecInfo && "Function template specialization info missing?");
- {
- // Note: do not overwrite location info if previous template
- // specialization kind was explicit.
- TemplateSpecializationKind TSK = SpecInfo->getTemplateSpecializationKind();
- if (TSK == TSK_Undeclared || TSK == TSK_ImplicitInstantiation)
- Specialization->setLocation(FD->getLocation());
- }
+
+ // Note: do not overwrite location info if previous template
+ // specialization kind was explicit.
+ TemplateSpecializationKind TSK = SpecInfo->getTemplateSpecializationKind();
+ if (TSK == TSK_Undeclared || TSK == TSK_ImplicitInstantiation)
+ Specialization->setLocation(FD->getLocation());
// FIXME: Check if the prior specialization has a point of instantiation.
// If so, we have run afoul of .