From 6131b4418387d55374bda7ddb211ff3e6656cb86 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Sat, 12 Dec 2009 18:16:41 +0000 Subject: 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. llvm-svn: 91218 --- clang/lib/Sema/TreeTransform.h | 70 +++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 35 deletions(-) (limited to 'clang/lib/Sema/TreeTransform.h') diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 643489fa374..f8e8f947be3 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -993,19 +993,6 @@ public: move(LHS), move(RHS)); } - /// \brief Build a new implicit cast expression. - /// - /// By default, builds a new implicit cast without any semantic analysis. - /// Subclasses may override this routine to provide different behavior. - OwningExprResult RebuildImplicitCastExpr(QualType T, CastExpr::CastKind Kind, - ExprArg SubExpr, bool isLvalue) { - ImplicitCastExpr *ICE - = new (getSema().Context) ImplicitCastExpr(T, Kind, - (Expr *)SubExpr.release(), - isLvalue); - return getSema().Owned(ICE); - } - /// \brief Build a new C-style cast expression. /// /// By default, performs semantic analysis to build the new expression. @@ -3779,29 +3766,39 @@ TreeTransform::TransformConditionalOperator(ConditionalOperator *E) { move(RHS)); } -template -Sema::OwningExprResult -TreeTransform::TransformImplicitCastExpr(ImplicitCastExpr *E) { - TemporaryBase Rebase(*this, E->getLocStart(), DeclarationName()); +/// \brief Given a cast expression, extract the subexpression of the +/// cast, looking through intermediate AST nodes that were generated +/// as part of type checking. +static Expr *getCastSubExprAsWritten(CastExpr *E) { + Expr *SubExpr = 0; + do { + SubExpr = E->getSubExpr(); - // FIXME: Will we ever have type information here? It seems like we won't, - // so do we even need to transform the type? - QualType T = getDerived().TransformType(E->getType()); - if (T.isNull()) - return SemaRef.ExprError(); + // Temporaries will be re-bound when rebuilding the original cast + // expression. + if (CXXBindTemporaryExpr *Binder = dyn_cast(SubExpr)) + SubExpr = Binder->getSubExpr(); - OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr()); - if (SubExpr.isInvalid()) - return SemaRef.ExprError(); + // Conversions by constructor and conversion functions have a + // subexpression describing the call; strip it off. + if (E->getCastKind() == CastExpr::CK_ConstructorConversion) + SubExpr = cast(SubExpr)->getArg(0); + else if (E->getCastKind() == CastExpr::CK_UserDefinedConversion) + SubExpr = cast(SubExpr)->getImplicitObjectArgument(); - if (!getDerived().AlwaysRebuild() && - T == E->getType() && - SubExpr.get() == E->getSubExpr()) - return SemaRef.Owned(E->Retain()); + // If the subexpression we're left with is an implicit cast, look + // through that, too. + } while ((E = dyn_cast(SubExpr))); - return getDerived().RebuildImplicitCastExpr(T, E->getCastKind(), - move(SubExpr), - E->isLvalueCast()); + return SubExpr; +} + +template +Sema::OwningExprResult +TreeTransform::TransformImplicitCastExpr(ImplicitCastExpr *E) { + // Implicit casts are eliminated during transformation, since they + // will be recomputed by semantic analysis after transformation. + return getDerived().TransformExpr(getCastSubExprAsWritten(E)); } template @@ -3826,7 +3823,8 @@ TreeTransform::TransformCStyleCastExpr(CStyleCastExpr *E) { return SemaRef.ExprError(); } - OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr()); + OwningExprResult SubExpr + = getDerived().TransformExpr(getCastSubExprAsWritten(E)); if (SubExpr.isInvalid()) return SemaRef.ExprError(); @@ -4182,7 +4180,8 @@ TreeTransform::TransformCXXNamedCastExpr(CXXNamedCastExpr *E) { return SemaRef.ExprError(); } - OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr()); + OwningExprResult SubExpr + = getDerived().TransformExpr(getCastSubExprAsWritten(E)); if (SubExpr.isInvalid()) return SemaRef.ExprError(); @@ -4246,7 +4245,8 @@ TreeTransform::TransformCXXFunctionalCastExpr( return SemaRef.ExprError(); } - OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr()); + OwningExprResult SubExpr + = getDerived().TransformExpr(getCastSubExprAsWritten(E)); if (SubExpr.isInvalid()) return SemaRef.ExprError(); -- cgit v1.2.3