aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-05-19 23:10:31 +0000
committerDouglas Gregor <dgregor@apple.com>2009-05-19 23:10:31 +0000
commitdd0273078111ec7312172c456a01ff86bff83b23 (patch)
tree3164cd45a50628b9c82738c815e17fa343783d36
parentc9ecc57d6d1fd4a96c748e52958d70be3b3da9fb (diff)
Template instantiation for __builtin_va_arg.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72144 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaExpr.cpp6
-rw-r--r--lib/Sema/SemaTemplateInstantiateExpr.cpp30
-rw-r--r--test/SemaTemplate/instantiate-expr-3.cpp16
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>;