[cfe-commits] r80422 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaTemplate/instantiate-member-initializers.cpp
Anders Carlsson
andersca at mac.com
Fri Aug 28 22:16:23 PDT 2009
Author: andersca
Date: Sat Aug 29 00:16:22 2009
New Revision: 80422
URL: http://llvm.org/viewvc/llvm-project?rev=80422&view=rev
Log:
Instantiate member and base initializers. Patch by Anders Johnsen! (tweaked slightly by me)
Added:
cfe/trunk/test/SemaTemplate/instantiate-member-initializers.cpp
Modified:
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=80422&r1=80421&r2=80422&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Sat Aug 29 00:16:22 2009
@@ -2960,6 +2960,10 @@
VarDecl *Var,
bool Recursive = false);
+ void InstantiateMemInitializers(CXXConstructorDecl *New,
+ const CXXConstructorDecl *Tmpl,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
NamedDecl *FindInstantiatedDecl(NamedDecl *D);
DeclContext *FindInstantiatedContext(DeclContext *DC);
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=80422&r1=80421&r2=80422&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Sat Aug 29 00:16:22 2009
@@ -992,9 +992,18 @@
DeclContext *PreviousContext = CurContext;
CurContext = Function;
+ MultiLevelTemplateArgumentList TemplateArgs =
+ getTemplateInstantiationArgs(Function);
+
+ // If this is a constructor, instantiate the member initializers.
+ if (const CXXConstructorDecl *Ctor =
+ dyn_cast<CXXConstructorDecl>(PatternDecl)) {
+ InstantiateMemInitializers(cast<CXXConstructorDecl>(Function), Ctor,
+ TemplateArgs);
+ }
+
// Instantiate the function body.
- OwningStmtResult Body
- = SubstStmt(Pattern, getTemplateInstantiationArgs(Function));
+ OwningStmtResult Body = SubstStmt(Pattern, TemplateArgs);
ActOnFinishFunctionBody(DeclPtrTy::make(Function), move(Body),
/*IsInstantiation=*/true);
@@ -1092,6 +1101,71 @@
}
}
+void
+Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
+ const CXXConstructorDecl *Tmpl,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+
+ llvm::SmallVector<MemInitTy*, 4> NewInits;
+
+ // Instantiate all the initializers.
+ for (CXXConstructorDecl::init_const_iterator Inits = Tmpl->init_begin(),
+ InitsEnd = Tmpl->init_end(); Inits != InitsEnd; ++Inits) {
+ CXXBaseOrMemberInitializer *Init = *Inits;
+
+ ASTOwningVector<&ActionBase::DeleteExpr> NewArgs(*this);
+
+ // Instantiate all the arguments.
+ for (ExprIterator Args = Init->arg_begin(), ArgsEnd = Init->arg_end();
+ Args != ArgsEnd; ++Args) {
+ OwningExprResult NewArg = SubstExpr(*Args, TemplateArgs);
+
+ if (NewArg.isInvalid())
+ New->setInvalidDecl();
+ else
+ NewArgs.push_back(NewArg.takeAs<Expr>());
+ }
+
+ MemInitResult NewInit;
+
+ if (Init->isBaseInitializer()) {
+ // FIXME: Type needs to be instantiated.
+ QualType BaseType =
+ Context.getCanonicalType(QualType(Init->getBaseClass(), 0));
+
+ NewInit = BuildBaseInitializer(BaseType,
+ (Expr **)NewArgs.data(),
+ NewArgs.size(),
+ Init->getSourceLocation(),
+ Init->getRParenLoc(),
+ New->getParent());
+ } else if (Init->isMemberInitializer()) {
+ FieldDecl *Member =
+ cast<FieldDecl>(FindInstantiatedDecl(Init->getMember()));
+
+ NewInit = BuildMemberInitializer(Member, (Expr **)NewArgs.data(),
+ NewArgs.size(),
+ Init->getSourceLocation(),
+ Init->getRParenLoc());
+ }
+
+ if (NewInit.isInvalid())
+ New->setInvalidDecl();
+ else {
+ // FIXME: It would be nice if ASTOwningVector had a release function.
+ NewArgs.take();
+
+ NewInits.push_back((MemInitTy *)NewInit.get());
+ }
+ }
+
+ // Assign all the initializers to the new constructor.
+ ActOnMemInitializers(DeclPtrTy::make(New),
+ /*FIXME: ColonLoc */
+ SourceLocation(),
+ NewInits.data(), NewInits.size());
+}
+
static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) {
if (D->getKind() != Other->getKind())
return false;
Added: cfe/trunk/test/SemaTemplate/instantiate-member-initializers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-member-initializers.cpp?rev=80422&view=auto
==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-member-initializers.cpp (added)
+++ cfe/trunk/test/SemaTemplate/instantiate-member-initializers.cpp Sat Aug 29 00:16:22 2009
@@ -0,0 +1,20 @@
+// RUN: clang-cc -fsyntax-only -Wall -verify %s
+
+template<typename T> struct A {
+ A() : a(1) { } // expected-error{{incompatible type passing 'int', expected 'void *'}}
+
+ T a;
+};
+
+A<int> a0;
+A<void*> a1; // expected-note{{in instantiation of member function 'A<void *>::A' requested here}}
+
+template<typename T> struct B {
+ // FIXME: This should warn about initialization order
+ B() : b(1), a(2) { }
+
+ int a;
+ int b;
+};
+
+B<int> b0;
More information about the cfe-commits
mailing list