diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-12-23 23:03:06 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-12-23 23:03:06 +0000 |
commit | 036aed18662e0193aafe0e8ae13d2e57efe6df25 (patch) | |
tree | 40e67da6505f06471a854249e0a3ac17fd1c6045 | |
parent | 8d9fb9b21364892b5e41ebfacdad8f41414d2b89 (diff) |
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
-rw-r--r-- | include/clang/AST/ExprCXX.h | 25 | ||||
-rw-r--r-- | lib/AST/ExprCXX.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 8 | ||||
-rw-r--r-- | test/SemaTemplate/default-expr-arguments.cpp | 17 |
6 files changed, 46 insertions, 18 deletions
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<ParmVarDecl *, 1, bool> 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<Expr **>(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<Expr>())); } @@ -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<FunctionDecl>(E->getParam()->getDeclContext())-> getDescribedFunctionTemplate() && "Default arg expressions are never formed in dependent cases."); - return SemaRef.Owned(E->Retain()); + return SemaRef.BuildCXXDefaultArgExpr(E->getUsedLocation(), + cast<FunctionDecl>(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<Derived>::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E) { Param == E->getParam()) return SemaRef.Owned(E->Retain()); - return getDerived().RebuildCXXDefaultArgExpr(Param); + return getDerived().RebuildCXXDefaultArgExpr(E->getUsedLocation(), Param); } template<typename Derived> 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<typename T> 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<typename T> struct vector { - vector(const allocator<T>& = allocator<T>()) {} // expected-note{{instantiation of}} + vector(const allocator<T>& = allocator<T>()) {} // expected-note2 {{instantiation of}} }; struct A { }; - + struct B { }; + template<typename> void FilterVTs() { vector<A> Result; @@ -165,4 +166,14 @@ namespace PR5810 { void f() { vector<A> Result; } + + template<typename T> + struct X { + vector<B> bs; + X() { } + }; + + void f2() { + X<float> x; // expected-note{{member function}} + } } |