diff options
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateExpr.cpp | 30 | ||||
-rw-r--r-- | test/SemaTemplate/instantiate-expr-3.cpp | 16 |
3 files changed, 47 insertions, 5 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index d268658454..d72d56f1d6 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -5253,11 +5253,13 @@ Sema::OwningExprResult Sema::ActOnVAArg(SourceLocation BuiltinLoc, } else { // Otherwise, the va_list argument must be an l-value because // it is modified by va_arg. - if (CheckForModifiableLvalue(E, BuiltinLoc, *this)) + if (!E->isTypeDependent() && + CheckForModifiableLvalue(E, BuiltinLoc, *this)) return ExprError(); } - if (!Context.hasSameType(VaListType, E->getType())) { + if (!E->isTypeDependent() && + !Context.hasSameType(VaListType, E->getType())) { return ExprError(Diag(E->getLocStart(), diag::err_first_argument_to_va_arg_not_of_type_va_list) << OrigExpr->getType() << E->getSourceRange()); diff --git a/lib/Sema/SemaTemplateInstantiateExpr.cpp b/lib/Sema/SemaTemplateInstantiateExpr.cpp index 92a152c2e3..56126d4504 100644 --- a/lib/Sema/SemaTemplateInstantiateExpr.cpp +++ b/lib/Sema/SemaTemplateInstantiateExpr.cpp @@ -59,6 +59,7 @@ namespace { OwningExprResult VisitTypesCompatibleExpr(TypesCompatibleExpr *E); OwningExprResult VisitShuffleVectorExpr(ShuffleVectorExpr *E); OwningExprResult VisitChooseExpr(ChooseExpr *E); + OwningExprResult VisitVAArgExpr(VAArgExpr *E); OwningExprResult VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E); OwningExprResult VisitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *E); OwningExprResult VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E); @@ -162,12 +163,17 @@ TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) { *Arg.getAsIntegral(), T, E->getSourceRange().getBegin())); - } else if (ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) + } else if (ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) { NewD = SemaRef.CurrentInstantiationScope->getInstantiationOf(Parm); - else if (isa<FunctionDecl>(D) || isa<OverloadedFunctionDecl>(D)) + } else if (VarDecl *Var = dyn_cast<VarDecl>(D)) { + if (Var->hasLocalStorage()) + NewD = SemaRef.CurrentInstantiationScope->getInstantiationOf(Var); + else + assert(false && "Cannot instantiation non-local variable declarations"); + } else if (isa<FunctionDecl>(D) || isa<OverloadedFunctionDecl>(D)) { // FIXME: Instantiate decl! NewD = cast<ValueDecl>(D); - else + } else assert(false && "Unhandled declaratrion reference kind"); if (!NewD) @@ -540,6 +546,24 @@ TemplateExprInstantiator::VisitChooseExpr(ChooseExpr *E) { E->getRParenLoc()); } +Sema::OwningExprResult TemplateExprInstantiator::VisitVAArgExpr(VAArgExpr *E) { + OwningExprResult SubExpr = Visit(E->getSubExpr()); + if (SubExpr.isInvalid()) + return SemaRef.ExprError(); + + SourceLocation FakeTypeLoc + = SemaRef.PP.getLocForEndOfToken(E->getSubExpr()->getSourceRange() + .getEnd()); + QualType T = SemaRef.InstantiateType(E->getType(), TemplateArgs, + /*FIXME:*/FakeTypeLoc, + DeclarationName()); + if (T.isNull()) + return SemaRef.ExprError(); + + return SemaRef.ActOnVAArg(E->getBuiltinLoc(), move(SubExpr), + T.getAsOpaquePtr(), E->getRParenLoc()); +} + Sema::OwningExprResult TemplateExprInstantiator::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { bool isSizeOf = E->isSizeOf(); diff --git a/test/SemaTemplate/instantiate-expr-3.cpp b/test/SemaTemplate/instantiate-expr-3.cpp index df2bdc4261..7032b1dfdf 100644 --- a/test/SemaTemplate/instantiate-expr-3.cpp +++ b/test/SemaTemplate/instantiate-expr-3.cpp @@ -100,3 +100,19 @@ struct Choose0 { template struct Choose0<true, int, float, int&>; template struct Choose0<false, int, float, float&>; template struct Choose0<true, int, float, float&>; // expected-note{{instantiation}} + +// --------------------------------------------------------------------- +// va_arg +// --------------------------------------------------------------------- +template<typename ArgType> +struct VaArg0 { + void f(int n, ...) { + __builtin_va_list va; + __builtin_va_start(va, n); + for (int i = 0; i != n; ++i) + (void)__builtin_va_arg(va, ArgType); + __builtin_va_end(va); + } +}; + +template struct VaArg0<int>; |