aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-07-15 05:09:51 +0000
committerJohn McCall <rjmccall@apple.com>2011-07-15 05:09:51 +0000
commit91a5755ad73c5dc1dfb167e448fdd74e75a6df56 (patch)
tree3d9cea0acd2fabd28652ff520f22a80b9408f54e /lib/Sema
parent165622faa4a472ff94352dee534e2adeaac9c824 (diff)
Create a new expression node, SubstNonTypeTemplateParmExpr,
to represent a fully-substituted non-type template parameter. This should improve source fidelity, as well as being generically useful for diagnostics and such. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@135243 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/SemaTemplate.cpp54
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp109
-rw-r--r--lib/Sema/TreeTransform.h8
3 files changed, 85 insertions, 86 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 2b3e10e661..2514b48de3 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -3316,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:
//
@@ -3330,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
@@ -3346,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();
@@ -3563,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;
}
@@ -3610,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) {
@@ -4149,16 +4152,7 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
else
BT = T;
- Expr *E = IntegerLiteral::Create(Context, *Arg.getAsIntegral(), BT, Loc);
- if (T->isEnumeralType()) {
- // FIXME: This is a hack. We need a better way to handle substituted
- // non-type template parameters.
- E = CStyleCastExpr::Create(Context, T, VK_RValue, CK_IntegralCast, E, 0,
- Context.getTrivialTypeSourceInfo(T, Loc),
- Loc, Loc);
- }
-
- return Owned(E);
+ return Owned(IntegerLiteral::Create(Context, *Arg.getAsIntegral(), BT, Loc));
}
/// \brief Match two template parameters within template parameter lists.
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index edafb00c22..1988f14458 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -800,6 +800,11 @@ namespace {
getSema().CallsUndergoingInstantiation.pop_back();
return move(Result);
}
+
+ private:
+ ExprResult transformNonTypeTemplateParmRef(NonTypeTemplateParmDecl *parm,
+ SourceLocation loc,
+ const TemplateArgument &arg);
};
}
@@ -1078,46 +1083,65 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
}
+ return transformNonTypeTemplateParmRef(NTTP, E->getLocation(), Arg);
+}
+
+ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
+ NonTypeTemplateParmDecl *parm,
+ SourceLocation loc,
+ const TemplateArgument &arg) {
+ ExprResult result;
+ QualType type;
+
// The template argument itself might be an expression, in which
// case we just return that expression.
- if (Arg.getKind() == TemplateArgument::Expression)
- return SemaRef.Owned(Arg.getAsExpr());
+ if (arg.getKind() == TemplateArgument::Expression) {
+ Expr *argExpr = arg.getAsExpr();
+ result = SemaRef.Owned(argExpr);
+ type = argExpr->getType();
- if (Arg.getKind() == TemplateArgument::Declaration) {
- ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
+ } else if (arg.getKind() == TemplateArgument::Declaration) {
+ ValueDecl *VD = cast<ValueDecl>(arg.getAsDecl());
// Find the instantiation of the template argument. This is
// required for nested templates.
VD = cast_or_null<ValueDecl>(
- getSema().FindInstantiatedDecl(E->getLocation(),
- VD, TemplateArgs));
+ getSema().FindInstantiatedDecl(loc, VD, TemplateArgs));
if (!VD)
return ExprError();
// Derive the type we want the substituted decl to have. This had
// better be non-dependent, or these checks will have serious problems.
- QualType TargetType;
- if (NTTP->isExpandedParameterPack())
- TargetType = NTTP->getExpansionType(
- getSema().ArgumentPackSubstitutionIndex);
- else if (NTTP->isParameterPack() &&
- isa<PackExpansionType>(NTTP->getType())) {
- TargetType = SemaRef.SubstType(
- cast<PackExpansionType>(NTTP->getType())->getPattern(),
- TemplateArgs, E->getLocation(),
- NTTP->getDeclName());
- } else
- TargetType = SemaRef.SubstType(NTTP->getType(), TemplateArgs,
- E->getLocation(), NTTP->getDeclName());
- assert(!TargetType.isNull() && "type substitution failed for param type");
- assert(!TargetType->isDependentType() && "param type still dependent");
- return SemaRef.BuildExpressionFromDeclTemplateArgument(Arg,
- TargetType,
- E->getLocation());
+ if (parm->isExpandedParameterPack()) {
+ type = parm->getExpansionType(SemaRef.ArgumentPackSubstitutionIndex);
+ } else if (parm->isParameterPack() &&
+ isa<PackExpansionType>(parm->getType())) {
+ type = SemaRef.SubstType(
+ cast<PackExpansionType>(parm->getType())->getPattern(),
+ TemplateArgs, loc, parm->getDeclName());
+ } else {
+ type = SemaRef.SubstType(parm->getType(), TemplateArgs,
+ loc, parm->getDeclName());
+ }
+ assert(!type.isNull() && "type substitution failed for param type");
+ assert(!type->isDependentType() && "param type still dependent");
+ result = SemaRef.BuildExpressionFromDeclTemplateArgument(arg, type, loc);
+
+ if (!result.isInvalid()) type = result.get()->getType();
+ } else {
+ result = SemaRef.BuildExpressionFromIntegralTemplateArgument(arg, loc);
+
+ // Note that this type can be different from the type of 'result',
+ // e.g. if it's an enum type.
+ type = arg.getIntegralType();
}
+ if (result.isInvalid()) return ExprError();
- return SemaRef.BuildExpressionFromIntegralTemplateArgument(Arg,
- E->getSourceRange().getBegin());
+ Expr *resultExpr = result.take();
+ return SemaRef.Owned(new (SemaRef.Context)
+ SubstNonTypeTemplateParmExpr(type,
+ resultExpr->getValueKind(),
+ loc, parm, resultExpr));
}
ExprResult
@@ -1133,36 +1157,9 @@ TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr(
assert(Index < ArgPack.pack_size() && "Substitution index out-of-range");
const TemplateArgument &Arg = ArgPack.pack_begin()[Index];
- if (Arg.getKind() == TemplateArgument::Expression)
- return SemaRef.Owned(Arg.getAsExpr());
-
- if (Arg.getKind() == TemplateArgument::Declaration) {
- ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
-
- // Find the instantiation of the template argument. This is
- // required for nested templates.
- VD = cast_or_null<ValueDecl>(
- getSema().FindInstantiatedDecl(E->getParameterPackLocation(),
- VD, TemplateArgs));
- if (!VD)
- return ExprError();
-
- QualType T;
- NonTypeTemplateParmDecl *NTTP = E->getParameterPack();
- if (NTTP->isExpandedParameterPack())
- T = NTTP->getExpansionType(getSema().ArgumentPackSubstitutionIndex);
- else if (const PackExpansionType *Expansion
- = dyn_cast<PackExpansionType>(NTTP->getType()))
- T = SemaRef.SubstType(Expansion->getPattern(), TemplateArgs,
- E->getParameterPackLocation(), NTTP->getDeclName());
- else
- T = E->getType();
- return SemaRef.BuildExpressionFromDeclTemplateArgument(Arg, T,
- E->getParameterPackLocation());
- }
-
- return SemaRef.BuildExpressionFromIntegralTemplateArgument(Arg,
- E->getParameterPackLocation());
+ return transformNonTypeTemplateParmRef(E->getParameterPack(),
+ E->getParameterPackLocation(),
+ Arg);
}
ExprResult
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 040ba9ee12..0530b5a172 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -7665,6 +7665,14 @@ TreeTransform<Derived>::TransformSubstNonTypeTemplateParmPackExpr(
template<typename Derived>
ExprResult
+TreeTransform<Derived>::TransformSubstNonTypeTemplateParmExpr(
+ SubstNonTypeTemplateParmExpr *E) {
+ // Default behavior is to do nothing with this transformation.
+ return SemaRef.Owned(E);
+}
+
+template<typename Derived>
+ExprResult
TreeTransform<Derived>::TransformMaterializeTemporaryExpr(
MaterializeTemporaryExpr *E) {
return getDerived().TransformExpr(E->GetTemporaryExpr());