[cfe-commits] r67104 - in /cfe/trunk: include/clang/AST/DeclVisitor.h lib/Sema/CMakeLists.txt lib/Sema/Sema.h lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp
Douglas Gregor
dgregor at apple.com
Tue Mar 17 14:15:41 PDT 2009
Author: dgregor
Date: Tue Mar 17 16:15:40 2009
New Revision: 67104
URL: http://llvm.org/viewvc/llvm-project?rev=67104&view=rev
Log:
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.
Added:
cfe/trunk/include/clang/AST/DeclVisitor.h
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
Modified:
cfe/trunk/lib/Sema/CMakeLists.txt
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
Added: cfe/trunk/include/clang/AST/DeclVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclVisitor.h?rev=67104&view=auto
==============================================================================
--- cfe/trunk/include/clang/AST/DeclVisitor.h (added)
+++ cfe/trunk/include/clang/AST/DeclVisitor.h Tue Mar 17 16:15:40 2009
@@ -0,0 +1,49 @@
+//===--- DeclVisitor.h - Visitor for Decl subclasses ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the DeclVisitor interface.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_AST_DECLVISITOR_H
+#define LLVM_CLANG_AST_DECLVISITOR_H
+
+namespace clang {
+
+#define DISPATCH(NAME, CLASS) \
+ return static_cast<ImplClass*>(this)-> Visit##NAME(static_cast<CLASS*>(D))
+
+/// \brief A simple visitor class that helps create declaration visitors.
+template<typename ImplClass, typename RetTy=void>
+class DeclVisitor {
+public:
+ RetTy Visit(Decl *D) {
+ switch (D->getKind()) {
+ default: assert(false && "Decl that isn't part of DeclNodes.def!");
+#define DECL(Derived, Base) \
+ case Decl::Derived: DISPATCH(Derived##Decl, Derived##Decl);
+#define ABSTRACT_DECL(Derived, Base)
+#include "clang/AST/DeclNodes.def"
+ }
+ }
+
+ // If the implementation chooses not to implement a certain visit
+ // method, fall back to the parent.
+#define DECL(Derived, Base) \
+ RetTy Visit##Derived##Decl(Derived##Decl *D) { DISPATCH(Base, Base); }
+#define ABSTRACT_DECL(Derived, Base) DECL(Derived, Base)
+#include "clang/AST/DeclNodes.def"
+
+ RetTy VisitDecl(Decl *D) { return RetTy(); }
+};
+
+#undef DISPATCH
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_AST_DECLVISITOR_H
Modified: cfe/trunk/lib/Sema/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CMakeLists.txt?rev=67104&r1=67103&r2=67104&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/CMakeLists.txt (original)
+++ cfe/trunk/lib/Sema/CMakeLists.txt Tue Mar 17 16:15:40 2009
@@ -22,6 +22,7 @@
SemaStmt.cpp
SemaTemplate.cpp
SemaTemplateInstantiate.cpp
+ SemaTemplateInstantiateDecl.cpp
SemaType.cpp
)
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=67104&r1=67103&r2=67104&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Mar 17 16:15:40 2009
@@ -1864,6 +1864,10 @@
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs);
+ Decl *InstantiateDecl(Decl *D, DeclContext *Owner,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs);
+
bool
InstantiateBaseSpecifiers(ClassTemplateSpecializationDecl *ClassTemplateSpec,
ClassTemplateDecl *ClassTemplate);
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=67104&r1=67103&r2=67104&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Tue Mar 17 16:15:40 2009
@@ -1036,7 +1036,6 @@
// Start the definition of this instantiation.
ClassTemplateSpec->startDefinition();
-
// Instantiate the base class specifiers.
if (InstantiateBaseSpecifiers(ClassTemplateSpec, Template))
Invalid = true;
@@ -1049,155 +1048,19 @@
for (RecordDecl::decl_iterator Member = Pattern->decls_begin(),
MemberEnd = Pattern->decls_end();
Member != MemberEnd; ++Member) {
- if (TypedefDecl *Typedef = dyn_cast<TypedefDecl>(*Member)) {
- // FIXME: Simplified instantiation of typedefs needs to be made
- // "real".
- QualType T = Typedef->getUnderlyingType();
- if (T->isDependentType()) {
- T = InstantiateType(T, ClassTemplateSpec->getTemplateArgs(),
- ClassTemplateSpec->getNumTemplateArgs(),
- Typedef->getLocation(),
- Typedef->getDeclName());
- if (T.isNull()) {
- Invalid = true;
- T = Context.IntTy;
- }
- }
-
- // Create the new typedef
- TypedefDecl *New
- = TypedefDecl::Create(Context, ClassTemplateSpec,
- Typedef->getLocation(),
- Typedef->getIdentifier(),
- T);
- ClassTemplateSpec->addDecl(New);
- }
- else if (FieldDecl *Field = dyn_cast<FieldDecl>(*Member)) {
- // FIXME: Simplified instantiation of fields needs to be made
- // "real".
- bool InvalidDecl = false;
- QualType T = Field->getType();
- if (T->isDependentType()) {
- T = InstantiateType(T, ClassTemplateSpec->getTemplateArgs(),
- ClassTemplateSpec->getNumTemplateArgs(),
- Field->getLocation(),
- Field->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.
- Diag(Field->getLocation(), diag::err_field_instantiates_to_function)
- << T;
- T = QualType();
- InvalidDecl = true;
- }
- }
-
- Expr *BitWidth = Field->getBitWidth();
- if (InvalidDecl)
- BitWidth = 0;
- else if (BitWidth) {
- OwningExprResult InstantiatedBitWidth
- = InstantiateExpr(BitWidth,
- ClassTemplateSpec->getTemplateArgs(),
- ClassTemplateSpec->getNumTemplateArgs());
- if (InstantiatedBitWidth.isInvalid()) {
- Invalid = InvalidDecl = true;
- BitWidth = 0;
- } else
- BitWidth = (Expr *)InstantiatedBitWidth.release();
- }
-
- FieldDecl *New = CheckFieldDecl(Field->getDeclName(), T,
- ClassTemplateSpec,
- Field->getLocation(),
- Field->isMutable(),
- BitWidth,
- Field->getAccess(),
- 0);
- if (New) {
- ClassTemplateSpec->addDecl(New);
- Fields.push_back(New);
-
- if (InvalidDecl)
- New->setInvalidDecl();
-
- if (New->isInvalidDecl())
- Invalid = true;
- }
- } else if (StaticAssertDecl *SA = dyn_cast<StaticAssertDecl>(*Member)) {
- Expr *AssertExpr = SA->getAssertExpr();
-
- OwningExprResult InstantiatedAssertExpr
- = InstantiateExpr(AssertExpr,
- ClassTemplateSpec->getTemplateArgs(),
- ClassTemplateSpec->getNumTemplateArgs());
- if (!InstantiatedAssertExpr.isInvalid()) {
- OwningExprResult Message = Clone(SA->getMessage());
-
- Decl *New =
- (Decl *)ActOnStaticAssertDeclaration(SA->getLocation(),
- move(InstantiatedAssertExpr),
- move(Message));
- if (New->isInvalidDecl())
- Invalid = true;
-
- } else
+ Decl *NewMember = InstantiateDecl(*Member, ClassTemplateSpec,
+ ClassTemplateSpec->getTemplateArgs(),
+ ClassTemplateSpec->getNumTemplateArgs());
+ if (NewMember) {
+ if (NewMember->isInvalidDecl())
Invalid = true;
- } else if (EnumDecl *Enum = dyn_cast<EnumDecl>(*Member)) {
- // FIXME: Spaghetti, anyone?
- EnumDecl *New = EnumDecl::Create(Context, ClassTemplateSpec,
- Enum->getLocation(),
- Enum->getIdentifier(),
- /*PrevDecl=*/0);
- ClassTemplateSpec->addDecl(New);
- New->startDefinition();
-
- llvm::SmallVector<DeclTy *, 16> Enumerators;
-
- EnumConstantDecl *LastEnumConst = 0;
- for (EnumDecl::enumerator_iterator EC = Enum->enumerator_begin(),
- ECEnd = Enum->enumerator_end();
- EC != ECEnd; ++EC) {
- // The specified value for the enumerator.
- OwningExprResult Value = Owned((Expr *)0);
- if (Expr *UninstValue = EC->getInitExpr())
- Value = InstantiateExpr(UninstValue,
- ClassTemplateSpec->getTemplateArgs(),
- ClassTemplateSpec->getNumTemplateArgs());
-
- // Drop the initial value and continue.
- bool isInvalid = false;
- if (Value.isInvalid()) {
- Value = Owned((Expr *)0);
- isInvalid = true;
- }
-
- EnumConstantDecl *NewEnumConst
- = CheckEnumConstant(New, LastEnumConst,
- EC->getLocation(),
- EC->getIdentifier(),
- move(Value));
-
- if (isInvalid) {
- if (NewEnumConst)
- NewEnumConst->setInvalidDecl();
- New->setInvalidDecl();
- Invalid = true;
- }
-
- if (NewEnumConst) {
- New->addDecl(NewEnumConst);
- Enumerators.push_back(NewEnumConst);
- LastEnumConst = NewEnumConst;
- }
- }
-
- ActOnEnumBody(New->getLocation(), New,
- &Enumerators[0], Enumerators.size());
+ else if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember))
+ Fields.push_back(Field);
+ } else {
+ // FIXME: Eventually, a NULL return will mean that one of the
+ // instantiations was a semantic disaster, and we'll want to set
+ // Invalid = true. For now, we expect to skip some members that
+ // we can't yet handle.
}
}
Added: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=67104&view=auto
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (added)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Tue Mar 17 16:15:40 2009
@@ -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);
+}
+
More information about the cfe-commits
mailing list