Representation of template type parameters and non-type template
parameters, with some semantic analysis:
- Template parameters are introduced into template parameter scope
- Complain about template parameter shadowing (except in Microsoft mode)
Note that we leak template parameter declarations like crazy, a
problem we'll remedy once we actually create proper declarations for
templates.
Next up: dependent types and value-dependent/type-dependent
expressions.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@60597 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index e1b56ad..7c8b4b1 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -943,6 +943,8 @@
if (TypedefDecl *Typedef = dyn_cast<TypedefDecl>(Decl))
return getTypedefType(Typedef);
+ else if (TemplateTypeParmDecl *TP = dyn_cast<TemplateTypeParmDecl>(Decl))
+ return getTemplateTypeParmType(TP);
else if (ObjCInterfaceDecl *ObjCInterface = dyn_cast<ObjCInterfaceDecl>(Decl))
return getObjCInterfaceType(ObjCInterface);
@@ -982,6 +984,16 @@
return QualType(Decl->TypeForDecl, 0);
}
+/// getTemplateTypeParmType - Return the unique reference to the type
+/// for the specified template type parameter declaration.
+QualType ASTContext::getTemplateTypeParmType(TemplateTypeParmDecl *Decl) {
+ if (!Decl->TypeForDecl) {
+ Decl->TypeForDecl = new TemplateTypeParmType(Decl);
+ Types.push_back(Decl->TypeForDecl);
+ }
+ return QualType(Decl->TypeForDecl, 0);
+}
+
/// getObjCInterfaceType - Return the unique reference to the type for the
/// specified ObjC interface decl.
QualType ASTContext::getObjCInterfaceType(ObjCInterfaceDecl *Decl) {
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 5cb2a3e..7b5df1c 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -239,6 +239,8 @@
case CXXField: nCXXFieldDecls++; break;
case CXXRecord: nCXXSUC++; break;
// FIXME: Statistics for C++ decls.
+ case TemplateTypeParm:
+ case NonTypeTemplateParm:
case CXXMethod:
case CXXConstructor:
case CXXDestructor:
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 6be9eaf..a26803c 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -19,7 +19,23 @@
//===----------------------------------------------------------------------===//
// Decl Allocation/Deallocation Method Implementations
//===----------------------------------------------------------------------===//
-
+
+TemplateTypeParmDecl *
+TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ bool Typename) {
+ void *Mem = C.getAllocator().Allocate<TemplateTypeParmDecl>();
+ return new (Mem) TemplateTypeParmDecl(DC, L, Id, Typename);
+}
+
+NonTypeTemplateParmDecl *
+NonTypeTemplateParmDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, IdentifierInfo *Id,
+ QualType T, SourceLocation TypeSpecStartLoc) {
+ void *Mem = C.getAllocator().Allocate<NonTypeTemplateParmDecl>();
+ return new (Mem) NonTypeTemplateParmDecl(DC, L, Id, T, TypeSpecStartLoc);
+}
+
CXXFieldDecl *CXXFieldDecl::Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation L, IdentifierInfo *Id,
QualType T, bool Mut, Expr *BW) {
diff --git a/lib/AST/DeclSerialization.cpp b/lib/AST/DeclSerialization.cpp
index 8a4612b..29714c0 100644
--- a/lib/AST/DeclSerialization.cpp
+++ b/lib/AST/DeclSerialization.cpp
@@ -88,6 +88,10 @@
Dcl = TypedefDecl::CreateImpl(D, C);
break;
+ case TemplateTypeParm:
+ Dcl = TemplateTypeParmDecl::CreateImpl(D, C);
+ break;
+
case FileScopeAsm:
Dcl = FileScopeAsmDecl::CreateImpl(D, C);
break;
@@ -630,6 +634,27 @@
}
//===----------------------------------------------------------------------===//
+// TemplateTypeParmDecl Serialization.
+//===----------------------------------------------------------------------===//
+
+void TemplateTypeParmDecl::EmitImpl(Serializer& S) const {
+ S.EmitBool(Typename);
+ ScopedDecl::EmitInRec(S);
+ ScopedDecl::EmitOutRec(S);
+}
+
+TemplateTypeParmDecl *
+TemplateTypeParmDecl::CreateImpl(Deserializer& D, ASTContext& C) {
+ bool Typename = D.ReadBool();
+ void *Mem = C.getAllocator().Allocate<TemplateTypeParmDecl>();
+ TemplateTypeParmDecl *decl
+ = new (Mem) TemplateTypeParmDecl(0, SourceLocation(), NULL, Typename);
+ decl->ScopedDecl::ReadInRec(D, C);
+ decl->ScopedDecl::ReadOutRec(D, C);
+ return decl;
+}
+
+//===----------------------------------------------------------------------===//
// LinkageSpec Serialization.
//===----------------------------------------------------------------------===//
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index e4386ec..a3264b0 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -341,6 +341,12 @@
/// DeclCanBeLvalue - Determine whether the given declaration can be
/// an lvalue. This is a helper routine for isLvalue.
static bool DeclCanBeLvalue(const NamedDecl *Decl, ASTContext &Ctx) {
+ // C++ [temp.param]p6:
+ // A non-type non-reference template-parameter is not an lvalue.
+ if (const NonTypeTemplateParmDecl *NTTParm
+ = dyn_cast<NonTypeTemplateParmDecl>(Decl))
+ return NTTParm->getType()->isReferenceType();
+
return isa<VarDecl>(Decl) || isa<CXXFieldDecl>(Decl) ||
// C++ 3.10p2: An lvalue refers to an object or function.
(Ctx.getLangOptions().CPlusPlus &&
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 6aa3c8e..303fc7e 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -443,6 +443,11 @@
return dyn_cast<ObjCQualifiedIdType>(CanonicalType);
}
+const TemplateTypeParmType *Type::getAsTemplateTypeParmType() const {
+ // There is no sugar for template type parameters, so just return
+ // the canonical type pointer if it is the right class.
+ return dyn_cast<TemplateTypeParmType>(CanonicalType);
+}
bool Type::isIntegerType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
@@ -1002,6 +1007,12 @@
InnerString = getDecl()->getIdentifier()->getName() + InnerString;
}
+void TemplateTypeParmType::getAsStringInternal(std::string &InnerString) const {
+ if (!InnerString.empty()) // Prefix the basic type, e.g. 'parmname X'.
+ InnerString = ' ' + InnerString;
+ InnerString = getDecl()->getIdentifier()->getName() + InnerString;
+}
+
void ObjCInterfaceType::getAsStringInternal(std::string &InnerString) const {
if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
InnerString = ' ' + InnerString;
diff --git a/lib/AST/TypeSerialization.cpp b/lib/AST/TypeSerialization.cpp
index db93e4b..3bdc946 100644
--- a/lib/AST/TypeSerialization.cpp
+++ b/lib/AST/TypeSerialization.cpp
@@ -110,6 +110,10 @@
D.RegisterPtr(PtrID,TypedefType::CreateImpl(Context,D));
break;
+ case Type::TemplateTypeParm:
+ D.RegisterPtr(PtrID,TemplateTypeParmType::CreateImpl(Context, D));
+ break;
+
case Type::VariableArray:
D.RegisterPtr(PtrID,VariableArrayType::CreateImpl(Context,D));
break;
@@ -272,6 +276,25 @@
}
//===----------------------------------------------------------------------===//
+// TemplateTypeParmType
+//===----------------------------------------------------------------------===//
+
+void TemplateTypeParmType::EmitImpl(Serializer& S) const {
+ S.EmitPtr(getDecl());
+}
+
+Type* TemplateTypeParmType::CreateImpl(ASTContext& Context, Deserializer& D) {
+ std::vector<Type*>& Types =
+ const_cast<std::vector<Type*>&>(Context.getTypes());
+
+ TemplateTypeParmType* T = new TemplateTypeParmType(NULL);
+ Types.push_back(T);
+
+ D.ReadPtr(T->Decl); // May be backpatched.
+ return T;
+}
+
+//===----------------------------------------------------------------------===//
// VariableArrayType
//===----------------------------------------------------------------------===//