Introduce the notion of instantiation dependence into Clang's AST. A
type/expression/template argument/etc. is instantiation-dependent if
it somehow involves a template parameter, even if it doesn't meet the
requirements for the more common kinds of dependence (dependent type,
type-dependent expression, value-dependent expression).
When we see an instantiation-dependent type, we know we always need to
perform substitution into that instantiation-dependent type. This
keeps us from short-circuiting evaluation in places where we
shouldn't, and lets us properly implement C++0x [temp.type]p2.
In theory, this would also allow us to properly mangle
instantiation-dependent-but-not-dependent decltype types per the
Itanium C++ ABI, but we aren't quite there because we still mangle
based on the canonical type in cases like, e.g.,
template<unsigned> struct A { };
template<typename T>
void f(A<sizeof(sizeof(decltype(T() + T())))>) { }
template void f<int>(A<sizeof(sizeof(int))>);
and therefore get the wrong answer.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134225 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index d88b785..a7034aa 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -1898,6 +1898,7 @@
QualType CanonType;
+ bool InstantiationDependent = false;
if (TypeAliasTemplateDecl *AliasTemplate
= dyn_cast<TypeAliasTemplateDecl>(Template)) {
// Find the canonical type for this type alias template specialization.
@@ -1923,7 +1924,7 @@
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
@@ -4833,10 +4834,12 @@
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;
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index c452e26..675cef7 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -807,7 +807,7 @@
if (T.isNull())
return true;
- if (T->isDependentType() || T->isVariablyModifiedType())
+ if (T->isInstantiationDependentType() || T->isVariablyModifiedType())
return false;
getSema().MarkDeclarationsReferencedInType(Loc, T);
@@ -1340,7 +1340,7 @@
"Cannot perform an instantiation without some context on the "
"instantiation stack");
- if (!T->getType()->isDependentType() &&
+ if (!T->getType()->isInstantiationDependentType() &&
!T->getType()->isVariablyModifiedType())
return T;
@@ -1359,7 +1359,7 @@
if (TL.getType().isNull())
return 0;
- if (!TL.getType()->isDependentType() &&
+ if (!TL.getType()->isInstantiationDependentType() &&
!TL.getType()->isVariablyModifiedType()) {
// FIXME: Make a copy of the TypeLoc data here, so that we can
// return a new TypeSourceInfo. Inefficient!
@@ -1388,7 +1388,7 @@
// If T is not a dependent type or a variably-modified type, there
// is nothing to do.
- if (!T->isDependentType() && !T->isVariablyModifiedType())
+ if (!T->isInstantiationDependentType() && !T->isVariablyModifiedType())
return T;
TemplateInstantiator Instantiator(*this, TemplateArgs, Loc, Entity);
@@ -1396,7 +1396,8 @@
}
static bool NeedsInstantiationAsFunctionType(TypeSourceInfo *T) {
- if (T->getType()->isDependentType() || T->getType()->isVariablyModifiedType())
+ if (T->getType()->isInstantiationDependentType() ||
+ T->getType()->isVariablyModifiedType())
return true;
TypeLoc TL = T->getTypeLoc().IgnoreParens();
@@ -1410,7 +1411,7 @@
// The parameter's type as written might be dependent even if the
// decayed type was not dependent.
if (TypeSourceInfo *TSInfo = P->getTypeSourceInfo())
- if (TSInfo->getType()->isDependentType())
+ if (TSInfo->getType()->isInstantiationDependentType())
return true;
// TODO: currently we always rebuild expressions. When we
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 196e847..b6d5abf 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -132,7 +132,7 @@
bool IsTypeAlias) {
bool Invalid = false;
TypeSourceInfo *DI = D->getTypeSourceInfo();
- if (DI->getType()->isDependentType() ||
+ if (DI->getType()->isInstantiationDependentType() ||
DI->getType()->isVariablyModifiedType()) {
DI = SemaRef.SubstType(DI, TemplateArgs,
D->getLocation(), D->getDeclName());
@@ -435,7 +435,7 @@
Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
bool Invalid = false;
TypeSourceInfo *DI = D->getTypeSourceInfo();
- if (DI->getType()->isDependentType() ||
+ if (DI->getType()->isInstantiationDependentType() ||
DI->getType()->isVariablyModifiedType()) {
DI = SemaRef.SubstType(DI, TemplateArgs,
D->getLocation(), D->getDeclName());