aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaTemplateInstantiateDecl.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-12-12 18:16:41 +0000
committerDouglas Gregor <dgregor@apple.com>2009-12-12 18:16:41 +0000
commita88cfbfac9bbcbb9858f048d6d73a48711d8e93d (patch)
tree27d6e5d44d29a2f5c46ab790f6f83b590a682b13 /lib/Sema/SemaTemplateInstantiateDecl.cpp
parentd9c84c8381261530b16512d2aac146de8271ea1e (diff)
Rework the way we handle template instantiation for
implicitly-generated AST nodes. We previously built instantiated nodes for each of these AST nodes, then passed them on to Sema, which was not prepared to see already-type-checked nodes (see PR5755). In some places, we had ugly workarounds to try to avoid re-type-checking (e.g., in VarDecl initializer instantiation). Now, we skip implicitly-generated nodes when performing instantiation, preferring instead to build just the AST nodes that directly reflect what was written in the source code. This has several advantages: - We don't need to instantiate anything that doesn't have a direct correlation to the source code, so we can have better location information. - Semantic analysis sees the same thing at template instantiation time that it would see for a non-template. - At least one ugly hack (VarDecl initializers) goes away. Fixes PR5755. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91218 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp53
1 files changed, 42 insertions, 11 deletions
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 07e97117cb..4512bcde16 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -16,6 +16,7 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
#include "clang/Basic/PrettyStackTrace.h"
#include "clang/Lex/Preprocessor.h"
@@ -204,16 +205,6 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
= SemaRef.SubstExpr(D->getInit(), TemplateArgs);
if (Init.isInvalid())
Var->setInvalidDecl();
- else if (!D->getType()->isDependentType() &&
- !D->getInit()->isTypeDependent() &&
- !D->getInit()->isValueDependent()) {
- // If neither the declaration's type nor its initializer are dependent,
- // we don't want to redo all the checking, especially since the
- // initializer might have been wrapped by a CXXConstructExpr since we did
- // it the first time.
- Var->setType(D->getType());
- Var->setInit(SemaRef.Context, Init.takeAs<Expr>());
- }
else if (ParenListExpr *PLE = dyn_cast<ParenListExpr>((Expr *)Init.get())) {
// FIXME: We're faking all of the comma locations, which is suboptimal.
// Do we even need these comma locations?
@@ -239,7 +230,47 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
// When Init is destroyed, it will destroy the instantiated ParenListExpr;
// we've explicitly retained all of its subexpressions already.
- } else
+ } else if (CXXConstructExpr *Construct
+ = dyn_cast<CXXConstructExpr>((Expr *)Init.get())) {
+ // We build CXXConstructExpr nodes to capture the implicit
+ // construction of objects. Rip apart the CXXConstructExpr to
+ // pass its pieces down to the appropriate initialization
+ // function.
+ if (D->hasCXXDirectInitializer()) {
+ // FIXME: Poor source location information
+ SourceLocation FakeLParenLoc =
+ SemaRef.PP.getLocForEndOfToken(D->getLocation());
+ SourceLocation FakeRParenLoc = FakeLParenLoc;
+ llvm::SmallVector<SourceLocation, 4> FakeCommaLocs;
+ if (Construct->getNumArgs() > 0) {
+ FakeRParenLoc
+ = SemaRef.PP.getLocForEndOfToken(
+ Construct->getArg(Construct->getNumArgs() - 1)->getLocEnd());
+
+ FakeCommaLocs.reserve(Construct->getNumArgs() - 1);
+ for (unsigned I = 0, N = Construct->getNumArgs() - 1; I != N; ++I) {
+ Expr *E = Construct->getArg(I)->Retain();
+ FakeCommaLocs.push_back(
+ SemaRef.PP.getLocForEndOfToken(E->getLocEnd()));
+ }
+ Construct->getArg(Construct->getNumArgs() - 1)->Retain();
+ }
+
+ SemaRef.AddCXXDirectInitializerToDecl(Sema::DeclPtrTy::make(Var),
+ FakeLParenLoc,
+ Sema::MultiExprArg(SemaRef,
+ (void **)Construct->getArgs(),
+ Construct->getNumArgs()),
+ FakeCommaLocs.data(),
+ FakeRParenLoc);
+
+ } else if (Construct->getNumArgs() >= 1) {
+ SemaRef.AddInitializerToDecl(Sema::DeclPtrTy::make(Var),
+ SemaRef.Owned(Construct->getArg(0)->Retain()),
+ false);
+ } else
+ SemaRef.ActOnUninitializedDecl(Sema::DeclPtrTy::make(Var), false);
+ } else
SemaRef.AddInitializerToDecl(Sema::DeclPtrTy::make(Var), move(Init),
D->hasCXXDirectInitializer());
SemaRef.PopExpressionEvaluationContext();