diff options
author | Douglas Gregor <dgregor@apple.com> | 2008-12-05 18:15:24 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2008-12-05 18:15:24 +0000 |
commit | 72c3f314d92d65c050ee1c07b7753623c044d6c7 (patch) | |
tree | d714ab61b37fb6732d556e9f324181a41312cffa /lib/AST | |
parent | 8c56515a0c61b73fc2f02cc96dc3e37650d89d45 (diff) |
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
Diffstat (limited to 'lib/AST')
-rw-r--r-- | lib/AST/ASTContext.cpp | 12 | ||||
-rw-r--r-- | lib/AST/DeclBase.cpp | 2 | ||||
-rw-r--r-- | lib/AST/DeclCXX.cpp | 18 | ||||
-rw-r--r-- | lib/AST/DeclSerialization.cpp | 25 | ||||
-rw-r--r-- | lib/AST/Expr.cpp | 6 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 11 | ||||
-rw-r--r-- | lib/AST/TypeSerialization.cpp | 23 |
7 files changed, 96 insertions, 1 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index e1b56ad6fb..7c8b4b1b41 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -943,6 +943,8 @@ QualType ASTContext::getTypeDeclType(TypeDecl *Decl, TypeDecl* PrevDecl) { 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 @@ QualType ASTContext::getTypedefType(TypedefDecl *Decl) { 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 5cb2a3e64f..7b5df1c194 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -239,6 +239,8 @@ void Decl::addDeclKind(Kind k) { 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 6be9eaf1a3..a26803caec 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -19,7 +19,23 @@ using namespace clang; //===----------------------------------------------------------------------===// // 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 8a4612b674..29714c0125 100644 --- a/lib/AST/DeclSerialization.cpp +++ b/lib/AST/DeclSerialization.cpp @@ -88,6 +88,10 @@ Decl* Decl::Create(Deserializer& D, ASTContext& C) { 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 @@ TypedefDecl* TypedefDecl::CreateImpl(Deserializer& D, ASTContext& C) { } //===----------------------------------------------------------------------===// +// 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 e4386eceda..a3264b010b 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -341,6 +341,12 @@ bool Expr::hasLocalSideEffect() const { /// 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 6aa3c8eb38..303fc7e7ca 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -443,6 +443,11 @@ const ObjCQualifiedIdType *Type::getAsObjCQualifiedIdType() const { 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 @@ void TypedefType::getAsStringInternal(std::string &InnerString) const { 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 db93e4b103..3bdc946de7 100644 --- a/lib/AST/TypeSerialization.cpp +++ b/lib/AST/TypeSerialization.cpp @@ -110,6 +110,10 @@ void Type::Create(ASTContext& Context, unsigned i, Deserializer& D) { 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 @@ Type* TypedefType::CreateImpl(ASTContext& Context, Deserializer& D) { } //===----------------------------------------------------------------------===// +// 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 //===----------------------------------------------------------------------===// |