diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-03-17 21:15:40 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-03-17 21:15:40 +0000 |
commit | 8dbc2694424b4e842b1d5ea39744a137b58600c3 (patch) | |
tree | 277320c8ac80346b4aec5fa8ea1b8fea2e1e584a /lib/Sema/SemaTemplateInstantiateDecl.cpp | |
parent | e504952bc89f79fc9ff54d5641ab30bb07ec435e (diff) |
Refactor instantiation of declarations within a template into a much
cleaner visitor framework.
Added a visitor for declarations, which is quite similar to the
visitor for statatements.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67104 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp new file mode 100644 index 0000000000..906ea25822 --- /dev/null +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -0,0 +1,202 @@ +//===--- SemaTemplateInstantiateDecl.cpp - C++ Template Decl Instantiation ===/ +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===/ +// +// This file implements C++ template instantiation for declarations. +// +//===----------------------------------------------------------------------===/ +#include "Sema.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/DeclVisitor.h" +#include "clang/AST/Expr.h" +#include "llvm/Support/Compiler.h" + +using namespace clang; + +namespace { + class VISIBILITY_HIDDEN TemplateDeclInstantiator + : public DeclVisitor<TemplateDeclInstantiator, Decl *> + { + Sema &SemaRef; + DeclContext *Owner; + const TemplateArgument *TemplateArgs; + unsigned NumTemplateArgs; + + public: + typedef Sema::OwningExprResult OwningExprResult; + + TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs) + : SemaRef(SemaRef), Owner(Owner), TemplateArgs(TemplateArgs), + NumTemplateArgs(NumTemplateArgs) { } + + // FIXME: Once we get closer to completion, replace these + // manually-written declarations with automatically-generated ones + // from clang/AST/DeclNodes.def. + Decl *VisitTypedefDecl(TypedefDecl *D); + Decl *VisitFieldDecl(FieldDecl *D); + Decl *VisitStaticAssertDecl(StaticAssertDecl *D); + Decl *VisitEnumDecl(EnumDecl *D); + + // Base case. FIXME: Remove once we can instantiate everything. + Decl *VisitDecl(Decl *) { + return 0; + } + }; +} + +Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { + bool Invalid = false; + QualType T = D->getUnderlyingType(); + if (T->isDependentType()) { + T = SemaRef.InstantiateType(T, TemplateArgs, NumTemplateArgs, + D->getLocation(), + D->getDeclName()); + if (T.isNull()) { + Invalid = true; + T = SemaRef.Context.IntTy; + } + } + + // Create the new typedef + TypedefDecl *Typedef + = TypedefDecl::Create(SemaRef.Context, Owner, D->getLocation(), + D->getIdentifier(), T); + if (Invalid) + Typedef->setInvalidDecl(); + + Owner->addDecl(Typedef); + return Typedef; +} + +Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) { + bool Invalid = false; + QualType T = D->getType(); + if (T->isDependentType()) { + T = SemaRef.InstantiateType(T, TemplateArgs, NumTemplateArgs, + D->getLocation(), + D->getDeclName()); + if (!T.isNull() && T->isFunctionType()) { + // C++ [temp.arg.type]p3: + // If a declaration acquires a function type through a type + // dependent on a template-parameter and this causes a + // declaration that does not use the syntactic form of a + // function declarator to have function type, the program is + // ill-formed. + SemaRef.Diag(D->getLocation(), diag::err_field_instantiates_to_function) + << T; + T = QualType(); + Invalid = true; + } + } + + Expr *BitWidth = D->getBitWidth(); + if (Invalid) + BitWidth = 0; + else if (BitWidth) { + OwningExprResult InstantiatedBitWidth + = SemaRef.InstantiateExpr(BitWidth, TemplateArgs, NumTemplateArgs); + if (InstantiatedBitWidth.isInvalid()) { + Invalid = true; + BitWidth = 0; + } else + BitWidth = (Expr *)InstantiatedBitWidth.release(); + } + + FieldDecl *Field = SemaRef.CheckFieldDecl(D->getDeclName(), T, + cast<RecordDecl>(Owner), + D->getLocation(), + D->isMutable(), + BitWidth, + D->getAccess(), + 0); + if (Field) { + if (Invalid) + Field->setInvalidDecl(); + + Owner->addDecl(Field); + } + + return Field; +} + +Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) { + Expr *AssertExpr = D->getAssertExpr(); + + OwningExprResult InstantiatedAssertExpr + = SemaRef.InstantiateExpr(AssertExpr, TemplateArgs, NumTemplateArgs); + if (InstantiatedAssertExpr.isInvalid()) + return 0; + + OwningExprResult Message = SemaRef.Clone(D->getMessage()); + Decl *StaticAssert + = (Decl *)SemaRef.ActOnStaticAssertDeclaration(D->getLocation(), + move(InstantiatedAssertExpr), + move(Message)); + return StaticAssert; +} + +Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { + EnumDecl *Enum = EnumDecl::Create(SemaRef.Context, Owner, + D->getLocation(), D->getIdentifier(), + /*PrevDecl=*/0); + Owner->addDecl(Enum); + Enum->startDefinition(); + + llvm::SmallVector<Sema::DeclTy *, 16> Enumerators; + + EnumConstantDecl *LastEnumConst = 0; + for (EnumDecl::enumerator_iterator EC = D->enumerator_begin(), + ECEnd = D->enumerator_end(); + EC != ECEnd; ++EC) { + // The specified value for the enumerator. + OwningExprResult Value = SemaRef.Owned((Expr *)0); + if (Expr *UninstValue = EC->getInitExpr()) + Value = SemaRef.InstantiateExpr(UninstValue, + TemplateArgs, NumTemplateArgs); + + // Drop the initial value and continue. + bool isInvalid = false; + if (Value.isInvalid()) { + Value = SemaRef.Owned((Expr *)0); + isInvalid = true; + } + + EnumConstantDecl *EnumConst + = SemaRef.CheckEnumConstant(Enum, LastEnumConst, + EC->getLocation(), EC->getIdentifier(), + move(Value)); + + if (isInvalid) { + if (EnumConst) + EnumConst->setInvalidDecl(); + Enum->setInvalidDecl(); + } + + if (EnumConst) { + Enum->addDecl(EnumConst); + Enumerators.push_back(EnumConst); + LastEnumConst = EnumConst; + } + } + + SemaRef.ActOnEnumBody(Enum->getLocation(), Enum, + &Enumerators[0], Enumerators.size()); + + return Enum; +} + +Decl *Sema::InstantiateDecl(Decl *D, DeclContext *Owner, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs) { + TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs, + NumTemplateArgs); + return Instantiator.Visit(D); +} + |