aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2012-09-26 02:36:12 +0000
committerEli Friedman <eli.friedman@gmail.com>2012-09-26 02:36:12 +0000
commitd7a6b1640e565487d163023a6a2e83f55476ae96 (patch)
treed5f4472454c04080fc1f329d70b8c71c91b24aa0 /lib/Sema
parent073819806ba2441e2a3e550107f1e756a6ee3ad0 (diff)
Fix the AST representation for non-type template arguments to encode
enough information so we can mangle them correctly in cases involving dependent parameter types. (This specifically impacts cases involving null pointers and cases involving parameters of reference type.) Fix the mangler to use this information instead of trying to scavenge it out of the parameter declaration. <rdar://problem/12296776>. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@164656 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/SemaLookup.cpp1
-rw-r--r--lib/Sema/SemaTemplate.cpp88
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp66
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp7
-rw-r--r--lib/Sema/TreeTransform.h5
5 files changed, 107 insertions, 60 deletions
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 8da6f8da9c..d5efd757c8 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -1798,6 +1798,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result,
case TemplateArgument::Declaration:
case TemplateArgument::Integral:
case TemplateArgument::Expression:
+ case TemplateArgument::NullPtr:
// [Note: non-type template arguments do not contribute to the set of
// associated namespaces. ]
break;
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index bc40cbb8c9..0efe710acc 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -2843,6 +2843,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
case TemplateArgument::Declaration:
case TemplateArgument::Integral:
+ case TemplateArgument::NullPtr:
// We've already checked this template argument, so just copy
// it to the list of converted arguments.
Converted.push_back(Arg.getArgument());
@@ -2977,6 +2978,8 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
llvm_unreachable("Declaration argument with template template parameter");
case TemplateArgument::Integral:
llvm_unreachable("Integral argument with template template parameter");
+ case TemplateArgument::NullPtr:
+ llvm_unreachable("Null pointer argument with template template parameter");
case TemplateArgument::Pack:
llvm_unreachable("Caller must expand template argument packs");
@@ -3068,15 +3071,12 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
if (*Expansions == ArgumentPack.size()) {
// We're done with this parameter pack. Pack up its arguments and add
// them to the list.
- if (ArgumentPack.empty())
- Converted.push_back(TemplateArgument(0, 0));
- else {
- Converted.push_back(
- TemplateArgument::CreatePackCopy(Context,
- ArgumentPack.data(),
- ArgumentPack.size()));
- ArgumentPack.clear();
- }
+ Converted.push_back(
+ TemplateArgument::CreatePackCopy(Context,
+ ArgumentPack.data(),
+ ArgumentPack.size()));
+ ArgumentPack.clear();
+
// This argument is assigned to the next parameter.
++Param;
continue;
@@ -3143,15 +3143,11 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
// Push the argument pack onto the list of converted arguments.
if (InFinalParameterPack) {
- if (ArgumentPack.empty())
- Converted.push_back(TemplateArgument(0, 0));
- else {
- Converted.push_back(
- TemplateArgument::CreatePackCopy(Context,
- ArgumentPack.data(),
- ArgumentPack.size()));
- ArgumentPack.clear();
- }
+ Converted.push_back(
+ TemplateArgument::CreatePackCopy(Context,
+ ArgumentPack.data(),
+ ArgumentPack.size()));
+ ArgumentPack.clear();
} else if (ExpansionIntoFixedList) {
// We have expanded a pack into a fixed list.
*ExpansionIntoFixedList = true;
@@ -3185,14 +3181,10 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
if (Param + 1 != ParamEnd)
return true;
- if (ArgumentPack.empty())
- Converted.push_back(TemplateArgument(0, 0));
- else {
- Converted.push_back(TemplateArgument::CreatePackCopy(Context,
- ArgumentPack.data(),
- ArgumentPack.size()));
- ArgumentPack.clear();
- }
+ Converted.push_back(TemplateArgument::CreatePackCopy(Context,
+ ArgumentPack.data(),
+ ArgumentPack.size()));
+ ArgumentPack.clear();
++Param;
continue;
@@ -3679,7 +3671,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
switch (isNullPointerValueTemplateArgument(S, Param, ParamType, Arg)) {
case NPV_NullPointer:
S.Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
- Converted = TemplateArgument((Decl *)0);
+ Converted = TemplateArgument(ParamType, /*isNullPtr*/true);
return false;
case NPV_Error:
@@ -3767,7 +3759,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
return true;
}
- NamedDecl *Entity = DRE->getDecl();
+ ValueDecl *Entity = DRE->getDecl();
// Cannot refer to non-static data members
if (FieldDecl *Field = dyn_cast<FieldDecl>(Entity)) {
@@ -3955,7 +3947,8 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
}
// Create the template argument.
- Converted = TemplateArgument(Entity->getCanonicalDecl());
+ Converted = TemplateArgument(cast<ValueDecl>(Entity->getCanonicalDecl()),
+ ParamType->isReferenceType());
S.MarkAnyDeclReferenced(Arg->getLocStart(), Entity);
return false;
}
@@ -3976,7 +3969,7 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
return true;
case NPV_NullPointer:
S.Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
- Converted = TemplateArgument((Decl *)0);
+ Converted = TemplateArgument(ParamType, /*isNullPtr*/true);
return false;
case NPV_NotNullPointer:
break;
@@ -4045,10 +4038,12 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
if (isa<NonTypeTemplateParmDecl>(VD) ||
(isa<VarDecl>(VD) &&
S.Context.getCanonicalType(VD->getType()).isConstQualified())) {
- if (Arg->isTypeDependent() || Arg->isValueDependent())
+ if (Arg->isTypeDependent() || Arg->isValueDependent()) {
Converted = TemplateArgument(Arg);
- else
- Converted = TemplateArgument(VD->getCanonicalDecl());
+ } else {
+ VD = cast<ValueDecl>(VD->getCanonicalDecl());
+ Converted = TemplateArgument(VD, /*isReferenceParam*/false);
+ }
return Invalid;
}
}
@@ -4069,10 +4064,12 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
// Okay: this is the address of a non-static member, and therefore
// a member pointer constant.
- if (Arg->isTypeDependent() || Arg->isValueDependent())
+ if (Arg->isTypeDependent() || Arg->isValueDependent()) {
Converted = TemplateArgument(Arg);
- else
- Converted = TemplateArgument(DRE->getDecl()->getCanonicalDecl());
+ } else {
+ ValueDecl *D = cast<ValueDecl>(DRE->getDecl()->getCanonicalDecl());
+ Converted = TemplateArgument(D, /*isReferenceParam*/false);
+ }
return Invalid;
}
@@ -4425,7 +4422,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
case NPV_NullPointer:
Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
- Converted = TemplateArgument((Decl *)0);
+ Converted = TemplateArgument(ParamType, /*isNullPtr*/true);
return Owned(Arg);
}
}
@@ -4448,7 +4445,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param,
const TemplateArgumentLoc &Arg,
unsigned ArgumentPackIndex) {
- TemplateName Name = Arg.getArgument().getAsTemplate();
+ TemplateName Name = Arg.getArgument().getAsTemplateOrTemplatePattern();
TemplateDecl *Template = Name.getAsTemplateDecl();
if (!Template) {
// Any dependent template name is fine.
@@ -4497,12 +4494,9 @@ ExprResult
Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
QualType ParamType,
SourceLocation Loc) {
- assert(Arg.getKind() == TemplateArgument::Declaration &&
- "Only declaration template arguments permitted here");
-
// For a NULL non-type template argument, return nullptr casted to the
// parameter's type.
- if (!Arg.getAsDecl()) {
+ if (Arg.getKind() == TemplateArgument::NullPtr) {
return ImpCastExprToType(
new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc),
ParamType,
@@ -4510,7 +4504,9 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
? CK_NullToMemberPointer
: CK_NullToPointer);
}
-
+ assert(Arg.getKind() == TemplateArgument::Declaration &&
+ "Only declaration template arguments permitted here");
+
ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
if (VD->getDeclContext()->isRecord() &&
@@ -5105,10 +5101,10 @@ static bool CheckNonTypeClassTemplatePartialSpecializationArgs(Sema &S,
continue;
}
- Expr *ArgExpr = Args[I].getAsExpr();
- if (!ArgExpr) {
+ if (Args[I].getKind() != TemplateArgument::Expression)
continue;
- }
+
+ Expr *ArgExpr = Args[I].getAsExpr();
// We can have a pack expansion of any of the bullets below.
if (PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(ArgExpr))
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index b97a12a2cb..6b58087819 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -158,9 +158,6 @@ static NonTypeTemplateParmDecl *getDeducedParameterFromExpr(Expr *E) {
/// \brief Determine whether two declaration pointers refer to the same
/// declaration.
static bool isSameDeclaration(Decl *X, Decl *Y) {
- if (!X || !Y)
- return !X && !Y;
-
if (NamedDecl *NX = dyn_cast<NamedDecl>(X))
X = NX->getUnderlyingDecl();
if (NamedDecl *NY = dyn_cast<NamedDecl>(Y))
@@ -262,7 +259,27 @@ checkDeducedTemplateArguments(ASTContext &Context,
// If we deduced two declarations, make sure they they refer to the
// same declaration.
if (Y.getKind() == TemplateArgument::Declaration &&
- isSameDeclaration(X.getAsDecl(), Y.getAsDecl()))
+ isSameDeclaration(X.getAsDecl(), Y.getAsDecl()) &&
+ X.isDeclForReferenceParam() == Y.isDeclForReferenceParam())
+ return X;
+
+ // All other combinations are incompatible.
+ return DeducedTemplateArgument();
+
+ case TemplateArgument::NullPtr:
+ // If we deduced a null pointer and a dependent expression, keep the
+ // null pointer.
+ if (Y.getKind() == TemplateArgument::Expression)
+ return X;
+
+ // If we deduced a null pointer and an integral constant, keep the
+ // integral constant.
+ if (Y.getKind() == TemplateArgument::Integral)
+ return Y;
+
+ // If we deduced two null pointers, make sure they have the same type.
+ if (Y.getKind() == TemplateArgument::NullPtr &&
+ Context.hasSameType(X.getNullPtrType(), Y.getNullPtrType()))
return X;
// All other combinations are incompatible.
@@ -356,13 +373,15 @@ DeduceNonTypeTemplateArgument(Sema &S,
static Sema::TemplateDeductionResult
DeduceNonTypeTemplateArgument(Sema &S,
NonTypeTemplateParmDecl *NTTP,
- Decl *D,
+ ValueDecl *D,
TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
assert(NTTP->getDepth() == 0 &&
"Cannot deduce non-type template argument with depth > 0");
- DeducedTemplateArgument NewDeduced(D? D->getCanonicalDecl() : 0);
+ D = D ? cast<ValueDecl>(D->getCanonicalDecl()) : 0;
+ TemplateArgument New(D, NTTP->getType()->isReferenceType());
+ DeducedTemplateArgument NewDeduced(New);
DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
Deduced[NTTP->getIndex()],
NewDeduced);
@@ -615,7 +634,7 @@ FinishArgumentPackDeduction(Sema &S,
if (NewlyDeducedPacks[I].empty()) {
// If we deduced an empty argument pack, create it now.
- NewPack = DeducedTemplateArgument(TemplateArgument(0, 0));
+ NewPack = DeducedTemplateArgument(TemplateArgument::getEmptyPack());
} else {
TemplateArgument *ArgumentPack
= new (S.Context) TemplateArgument [NewlyDeducedPacks[I].size()];
@@ -1599,7 +1618,17 @@ DeduceTemplateArguments(Sema &S,
case TemplateArgument::Declaration:
if (Arg.getKind() == TemplateArgument::Declaration &&
- isSameDeclaration(Param.getAsDecl(), Arg.getAsDecl()))
+ isSameDeclaration(Param.getAsDecl(), Arg.getAsDecl()) &&
+ Param.isDeclForReferenceParam() == Arg.isDeclForReferenceParam())
+ return Sema::TDK_Success;
+
+ Info.FirstArg = Param;
+ Info.SecondArg = Arg;
+ return Sema::TDK_NonDeducedMismatch;
+
+ case TemplateArgument::NullPtr:
+ if (Arg.getKind() == TemplateArgument::NullPtr &&
+ S.Context.hasSameType(Param.getNullPtrType(), Arg.getNullPtrType()))
return Sema::TDK_Success;
Info.FirstArg = Param;
@@ -1870,7 +1899,11 @@ static bool isSameTemplateArg(ASTContext &Context,
Context.getCanonicalType(Y.getAsType());
case TemplateArgument::Declaration:
- return isSameDeclaration(X.getAsDecl(), Y.getAsDecl());
+ return isSameDeclaration(X.getAsDecl(), Y.getAsDecl()) &&
+ X.isDeclForReferenceParam() == Y.isDeclForReferenceParam();
+
+ case TemplateArgument::NullPtr:
+ return Context.hasSameType(X.getNullPtrType(), Y.getNullPtrType());
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion:
@@ -1940,6 +1973,14 @@ getTrivialTemplateArgumentLoc(Sema &S,
return TemplateArgumentLoc(TemplateArgument(E), E);
}
+ case TemplateArgument::NullPtr: {
+ Expr *E
+ = S.BuildExpressionFromDeclTemplateArgument(Arg, NTTPType, Loc)
+ .takeAs<Expr>();
+ return TemplateArgumentLoc(TemplateArgument(NTTPType, /*isNullPtr*/true),
+ E);
+ }
+
case TemplateArgument::Integral: {
Expr *E
= S.BuildExpressionFromIntegralTemplateArgument(Arg, Loc).takeAs<Expr>();
@@ -2613,7 +2654,7 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
== Param)
Builder.push_back(TemplateArgument(ExplicitArgs, NumExplicitArgs));
else
- Builder.push_back(TemplateArgument(0, 0));
+ Builder.push_back(TemplateArgument::getEmptyPack());
continue;
}
@@ -4510,6 +4551,11 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
case TemplateArgument::Declaration:
break;
+ case TemplateArgument::NullPtr:
+ MarkUsedTemplateParameters(Ctx, TemplateArg.getNullPtrType(), OnlyDeduced,
+ Depth, Used);
+ break;
+
case TemplateArgument::Type:
MarkUsedTemplateParameters(Ctx, TemplateArg.getAsType(), OnlyDeduced,
Depth, Used);
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index c44794e3e1..621f92bb67 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1174,10 +1174,11 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
result = SemaRef.Owned(argExpr);
type = argExpr->getType();
- } else if (arg.getKind() == TemplateArgument::Declaration) {
+ } else if (arg.getKind() == TemplateArgument::Declaration ||
+ arg.getKind() == TemplateArgument::NullPtr) {
ValueDecl *VD;
- if (Decl *D = arg.getAsDecl()) {
- VD = cast<ValueDecl>(D);
+ if (arg.getKind() == TemplateArgument::Declaration) {
+ VD = cast<ValueDecl>(arg.getAsDecl());
// Find the instantiation of the template argument. This is
// required for nested templates.
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index d3839c5a5c..975895dc8e 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -2464,6 +2464,7 @@ public:
case TemplateArgument::Declaration:
case TemplateArgument::Pack:
case TemplateArgument::TemplateExpansion:
+ case TemplateArgument::NullPtr:
llvm_unreachable("Pack expansion pattern has no parameter packs");
case TemplateArgument::Type:
@@ -2946,6 +2947,7 @@ void TreeTransform<Derived>::InventTemplateArgumentLoc(
case TemplateArgument::Declaration:
case TemplateArgument::Integral:
case TemplateArgument::Pack:
+ case TemplateArgument::NullPtr:
Output = TemplateArgumentLoc(Arg, TemplateArgumentLocInfo());
break;
}
@@ -2961,7 +2963,8 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
case TemplateArgument::Integral:
case TemplateArgument::Pack:
case TemplateArgument::Declaration:
- llvm_unreachable("Cannot transform");
+ case TemplateArgument::NullPtr:
+ llvm_unreachable("Unexpected TemplateArgument");
case TemplateArgument::Type: {
TypeSourceInfo *DI = Input.getTypeSourceInfo();