From: Douglas Gregor Date: Wed, 23 Dec 2009 23:03:06 +0000 (+0000) Subject: When we see a CXXDefaultArgExpr during template instantiation, rebuild X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=036aed18662e0193aafe0e8ae13d2e57efe6df25;p=clang When we see a CXXDefaultArgExpr during template instantiation, rebuild the default argument so that we're sure to mark any referenced declarations. This gets us another little step closer to fixing PR5810. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@92078 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 0eaae29a64..662dbb6972 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -393,16 +393,20 @@ class CXXDefaultArgExpr : public Expr { /// actual default expression is the subexpression. llvm::PointerIntPair Param; + /// \brief The location where the default argument expression was used. + SourceLocation Loc; + protected: - CXXDefaultArgExpr(StmtClass SC, ParmVarDecl *param) + CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param) : Expr(SC, param->hasUnparsedDefaultArg() ? param->getType().getNonReferenceType() : param->getDefaultArg()->getType()), - Param(param, false) { } + Param(param, false), Loc(Loc) { } - CXXDefaultArgExpr(StmtClass SC, ParmVarDecl *param, Expr *SubExpr) - : Expr(SC, SubExpr->getType()), Param(param, true) + CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param, + Expr *SubExpr) + : Expr(SC, SubExpr->getType()), Param(param, true), Loc(Loc) { *reinterpret_cast(this + 1) = SubExpr; } @@ -413,13 +417,16 @@ protected: public: // Param is the parameter whose default argument is used by this // expression. - static CXXDefaultArgExpr *Create(ASTContext &C, ParmVarDecl *Param) { - return new (C) CXXDefaultArgExpr(CXXDefaultArgExprClass, Param); + static CXXDefaultArgExpr *Create(ASTContext &C, SourceLocation Loc, + ParmVarDecl *Param) { + return new (C) CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param); } // Param is the parameter whose default argument is used by this // expression, and SubExpr is the expression that will actually be used. - static CXXDefaultArgExpr *Create(ASTContext &C, ParmVarDecl *Param, + static CXXDefaultArgExpr *Create(ASTContext &C, + SourceLocation Loc, + ParmVarDecl *Param, Expr *SubExpr); // Retrieve the parameter that the argument was created from. @@ -438,6 +445,10 @@ public: return getParam()->getDefaultArg(); } + /// \brief Retrieve the location where this default argument was actually + /// used. + SourceLocation getUsedLocation() const { return Loc; } + virtual SourceRange getSourceRange() const { // Default argument expressions have no representation in the // source, so they have an empty source range. diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index e4538fdfed..81584b7002 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -353,9 +353,11 @@ const char *CXXNamedCastExpr::getCastName() const { } CXXDefaultArgExpr * -CXXDefaultArgExpr::Create(ASTContext &C, ParmVarDecl *Param, Expr *SubExpr) { +CXXDefaultArgExpr::Create(ASTContext &C, SourceLocation Loc, + ParmVarDecl *Param, Expr *SubExpr) { void *Mem = C.Allocate(sizeof(CXXDefaultArgExpr) + sizeof(Stmt *)); - return new (Mem) CXXDefaultArgExpr(CXXDefaultArgExprClass, Param, SubExpr); + return new (Mem) CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param, + SubExpr); } void CXXDefaultArgExpr::DoDestroy(ASTContext &C) { diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index c56eeefffd..24bc29560d 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -3093,7 +3093,7 @@ Sema::OwningExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, return ExprError(); // Build the default argument expression. - return Owned(CXXDefaultArgExpr::Create(Context, Param, + return Owned(CXXDefaultArgExpr::Create(Context, CallLoc, Param, Result.takeAs())); } @@ -3107,7 +3107,7 @@ Sema::OwningExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, } // We already type-checked the argument, so we know it works. - return Owned(CXXDefaultArgExpr::Create(Context, Param)); + return Owned(CXXDefaultArgExpr::Create(Context, CallLoc, Param)); } /// ConvertArgumentsForCall - Converts the arguments specified in diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index dddb93c87e..d65b246567 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -785,7 +785,9 @@ Sema::OwningExprResult TemplateInstantiator::TransformCXXDefaultArgExpr( assert(!cast(E->getParam()->getDeclContext())-> getDescribedFunctionTemplate() && "Default arg expressions are never formed in dependent cases."); - return SemaRef.Owned(E->Retain()); + return SemaRef.BuildCXXDefaultArgExpr(E->getUsedLocation(), + cast(E->getParam()->getDeclContext()), + E->getParam()); } diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 5152a29755..e062a37f8e 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -1358,8 +1358,10 @@ public: /// By default, builds a new default-argument expression, which does not /// require any semantic analysis. Subclasses may override this routine to /// provide different behavior. - OwningExprResult RebuildCXXDefaultArgExpr(ParmVarDecl *Param) { - return getSema().Owned(CXXDefaultArgExpr::Create(getSema().Context, Param)); + OwningExprResult RebuildCXXDefaultArgExpr(SourceLocation Loc, + ParmVarDecl *Param) { + return getSema().Owned(CXXDefaultArgExpr::Create(getSema().Context, Loc, + Param)); } /// \brief Build a new C++ zero-initialization expression. @@ -4416,7 +4418,7 @@ TreeTransform::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E) { Param == E->getParam()) return SemaRef.Owned(E->Retain()); - return getDerived().RebuildCXXDefaultArgExpr(Param); + return getDerived().RebuildCXXDefaultArgExpr(E->getUsedLocation(), Param); } template diff --git a/test/SemaTemplate/default-expr-arguments.cpp b/test/SemaTemplate/default-expr-arguments.cpp index 0635801c9f..0edc504ea0 100644 --- a/test/SemaTemplate/default-expr-arguments.cpp +++ b/test/SemaTemplate/default-expr-arguments.cpp @@ -147,16 +147,17 @@ namespace pr5301 { namespace PR5810 { template struct allocator { - allocator() { int a[sizeof(T) ? -1 : -1]; } // expected-error{{array size is negative}} + allocator() { int a[sizeof(T) ? -1 : -1]; } // expected-error2 {{array size is negative}} }; template struct vector { - vector(const allocator& = allocator()) {} // expected-note{{instantiation of}} + vector(const allocator& = allocator()) {} // expected-note2 {{instantiation of}} }; struct A { }; - + struct B { }; + template void FilterVTs() { vector Result; @@ -165,4 +166,14 @@ namespace PR5810 { void f() { vector Result; } + + template + struct X { + vector bs; + X() { } + }; + + void f2() { + X x; // expected-note{{member function}} + } }