[cfe-commits] r66947 - in /cfe/trunk: Driver/RewriteObjC.cpp include/clang/AST/Expr.h include/clang/AST/ExprCXX.h lib/AST/ExprCXX.cpp lib/AST/StmtSerialization.cpp lib/AST/Type.cpp lib/Sema/Sema.h lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaLookup.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiate.cpp test/SemaTemplate/instantiate-expr-1.cpp
Douglas Gregor
dgregor at apple.com
Fri Mar 13 14:01:29 PDT 2009
Author: dgregor
Date: Fri Mar 13 16:01:28 2009
New Revision: 66947
URL: http://llvm.org/viewvc/llvm-project?rev=66947&view=rev
Log:
Implement template instantiation for several more kinds of expressions:
- C++ function casts, e.g., T(foo)
- sizeof(), alignof()
More importantly, this allows us to verify that we're performing
overload resolution during template instantiation, with
argument-dependent lookup and the "cached" results of name lookup from
the template definition.
Modified:
cfe/trunk/Driver/RewriteObjC.cpp
cfe/trunk/include/clang/AST/Expr.h
cfe/trunk/include/clang/AST/ExprCXX.h
cfe/trunk/lib/AST/ExprCXX.cpp
cfe/trunk/lib/AST/StmtSerialization.cpp
cfe/trunk/lib/AST/Type.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/SemaLookup.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/test/SemaTemplate/instantiate-expr-1.cpp
Modified: cfe/trunk/Driver/RewriteObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/RewriteObjC.cpp?rev=66947&r1=66946&r2=66947&view=diff
==============================================================================
--- cfe/trunk/Driver/RewriteObjC.cpp (original)
+++ cfe/trunk/Driver/RewriteObjC.cpp Fri Mar 13 16:01:28 2009
@@ -2553,8 +2553,8 @@
FT->getResultType(), SourceLocation());
// Build sizeof(returnType)
- SizeOfAlignOfExpr *sizeofExpr = new (Context) SizeOfAlignOfExpr(true, true,
- returnType.getAsOpaquePtr(),
+ SizeOfAlignOfExpr *sizeofExpr = new (Context) SizeOfAlignOfExpr(true,
+ returnType,
Context->getSizeType(),
SourceLocation(), SourceLocation());
// (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=66947&r1=66946&r2=66947&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Fri Mar 13 16:01:28 2009
@@ -692,20 +692,26 @@
} Argument;
SourceLocation OpLoc, RParenLoc;
public:
- SizeOfAlignOfExpr(bool issizeof, bool istype, void *argument,
+ SizeOfAlignOfExpr(bool issizeof, QualType T,
QualType resultType, SourceLocation op,
SourceLocation rp) :
Expr(SizeOfAlignOfExprClass, resultType,
- false, // Never type-dependent.
+ false, // Never type-dependent (C++ [temp.dep.expr]p3).
// Value-dependent if the argument is type-dependent.
- (istype ? QualType::getFromOpaquePtr(argument)->isDependentType()
- : static_cast<Expr*>(argument)->isTypeDependent())),
- isSizeof(issizeof), isType(istype), OpLoc(op), RParenLoc(rp) {
- if (isType)
- Argument.Ty = argument;
- else
- // argument was an Expr*, so cast it back to that to be safe
- Argument.Ex = static_cast<Expr*>(argument);
+ T->isDependentType()),
+ isSizeof(issizeof), isType(true), OpLoc(op), RParenLoc(rp) {
+ Argument.Ty = T.getAsOpaquePtr();
+ }
+
+ SizeOfAlignOfExpr(bool issizeof, Expr *E,
+ QualType resultType, SourceLocation op,
+ SourceLocation rp) :
+ Expr(SizeOfAlignOfExprClass, resultType,
+ false, // Never type-dependent (C++ [temp.dep.expr]p3).
+ // Value-dependent if the argument is type-dependent.
+ E->isTypeDependent()),
+ isSizeof(issizeof), isType(false), OpLoc(op), RParenLoc(rp) {
+ Argument.Ex = E;
}
virtual void Destroy(ASTContext& C);
Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=66947&r1=66946&r2=66947&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Fri Mar 13 16:01:28 2009
@@ -467,6 +467,8 @@
const_arg_iterator arg_begin() const { return Args; }
const_arg_iterator arg_end() const { return Args + NumArgs; }
+ unsigned getNumArgs() const { return NumArgs; }
+
virtual SourceRange getSourceRange() const {
return SourceRange(TyBeginLoc, RParenLoc);
}
Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=66947&r1=66946&r2=66947&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Fri Mar 13 16:01:28 2009
@@ -216,7 +216,10 @@
Expr **Args,
unsigned NumArgs,
SourceLocation rParenLoc)
- : Expr(CXXTemporaryObjectExprClass, writtenTy),
+ : Expr(CXXTemporaryObjectExprClass, writtenTy,
+ writtenTy->isDependentType(),
+ (writtenTy->isDependentType() ||
+ CallExpr::hasAnyValueDependentArguments(Args, NumArgs))),
TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc),
Constructor(Cons), Args(0), NumArgs(NumArgs) {
if (NumArgs > 0) {
Modified: cfe/trunk/lib/AST/StmtSerialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtSerialization.cpp?rev=66947&r1=66946&r2=66947&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtSerialization.cpp (original)
+++ cfe/trunk/lib/AST/StmtSerialization.cpp Fri Mar 13 16:01:28 2009
@@ -832,9 +832,14 @@
QualType Res = QualType::ReadVal(D);
SourceLocation OpLoc = SourceLocation::ReadVal(D);
SourceLocation RParenLoc = SourceLocation::ReadVal(D);
-
- return new SizeOfAlignOfExpr(isSizeof, isType, Argument, Res,
- OpLoc, RParenLoc);
+
+ if (isType)
+ return new (C) SizeOfAlignOfExpr(isSizeof,
+ QualType::getFromOpaquePtr(Argument),
+ Res, OpLoc, RParenLoc);
+
+ return new (C) SizeOfAlignOfExpr(isSizeof, (Expr *)Argument,
+ Res, OpLoc, RParenLoc);
}
void StmtExpr::EmitImpl(Serializer& S) const {
Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=66947&r1=66946&r2=66947&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Fri Mar 13 16:01:28 2009
@@ -967,9 +967,12 @@
}
void ClassTemplateSpecializationType::Destroy(ASTContext& C) {
- for (unsigned Arg = 0; Arg < NumArgs; ++Arg)
- if (Expr *E = getArg(Arg).getAsExpr())
- E->Destroy(C);
+ for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
+ // FIXME: Not all expressions get cloned, so we can't yet perform
+ // this destruction.
+ // if (Expr *E = getArg(Arg).getAsExpr())
+ // E->Destroy(C);
+ }
}
ClassTemplateSpecializationType::iterator
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=66947&r1=66946&r2=66947&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Fri Mar 13 16:01:28 2009
@@ -1188,6 +1188,11 @@
ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
void *TyOrEx, const SourceRange &ArgRange);
+ OwningExprResult CreateSizeOfAlignOfExpr(QualType T, SourceLocation OpLoc,
+ bool isSizeOf, SourceRange R);
+ OwningExprResult CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc,
+ bool isSizeOf, SourceRange R);
+
bool CheckAlignOfExpr(Expr *E, SourceLocation OpLoc, const SourceRange &R);
bool CheckSizeOfAlignOfOperand(QualType type, SourceLocation OpLoc,
const SourceRange &R, bool isSizeof);
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=66947&r1=66946&r2=66947&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Mar 13 16:01:28 2009
@@ -1220,6 +1220,50 @@
return CheckSizeOfAlignOfOperand(E->getType(), OpLoc, ExprRange, false);
}
+/// \brief Build a sizeof or alignof expression given a type operand.
+Action::OwningExprResult
+Sema::CreateSizeOfAlignOfExpr(QualType T, SourceLocation OpLoc,
+ bool isSizeOf, SourceRange R) {
+ if (T.isNull())
+ return ExprError();
+
+ if (!T->isDependentType() &&
+ CheckSizeOfAlignOfOperand(T, OpLoc, R, isSizeOf))
+ return ExprError();
+
+ // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
+ return Owned(new (Context) SizeOfAlignOfExpr(isSizeOf, T,
+ Context.getSizeType(), OpLoc,
+ R.getEnd()));
+}
+
+/// \brief Build a sizeof or alignof expression given an expression
+/// operand.
+Action::OwningExprResult
+Sema::CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc,
+ bool isSizeOf, SourceRange R) {
+ // Verify that the operand is valid.
+ bool isInvalid = false;
+ if (E->isTypeDependent()) {
+ // Delay type-checking for type-dependent expressions.
+ } else if (!isSizeOf) {
+ isInvalid = CheckAlignOfExpr(E, OpLoc, R);
+ } else if (E->isBitField()) { // C99 6.5.3.4p1.
+ Diag(OpLoc, diag::err_sizeof_alignof_bitfield) << 0;
+ isInvalid = true;
+ } else {
+ isInvalid = CheckSizeOfAlignOfOperand(E->getType(), OpLoc, R, true);
+ }
+
+ if (isInvalid)
+ return ExprError();
+
+ // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
+ return Owned(new (Context) SizeOfAlignOfExpr(isSizeOf, E,
+ Context.getSizeType(), OpLoc,
+ R.getEnd()));
+}
+
/// ActOnSizeOfAlignOfExpr - Handle @c sizeof(type) and @c sizeof @c expr and
/// the same for @c alignof and @c __alignof
/// Note that the ArgRange is invalid if isType is false.
@@ -1229,42 +1273,20 @@
// If error parsing type, ignore.
if (TyOrEx == 0) return ExprError();
- QualType ArgTy;
- SourceRange Range;
if (isType) {
- ArgTy = QualType::getFromOpaquePtr(TyOrEx);
- Range = ArgRange;
-
- // Verify that the operand is valid.
- if (CheckSizeOfAlignOfOperand(ArgTy, OpLoc, Range, isSizeof))
- return ExprError();
- } else {
- // Get the end location.
- Expr *ArgEx = (Expr *)TyOrEx;
- Range = ArgEx->getSourceRange();
- ArgTy = ArgEx->getType();
-
- // Verify that the operand is valid.
- bool isInvalid;
- if (!isSizeof) {
- isInvalid = CheckAlignOfExpr(ArgEx, OpLoc, Range);
- } else if (ArgEx->isBitField()) { // C99 6.5.3.4p1.
- Diag(OpLoc, diag::err_sizeof_alignof_bitfield) << 0;
- isInvalid = true;
- } else {
- isInvalid = CheckSizeOfAlignOfOperand(ArgTy, OpLoc, Range, true);
- }
-
- if (isInvalid) {
- DeleteExpr(ArgEx);
- return ExprError();
- }
- }
+ QualType ArgTy = QualType::getFromOpaquePtr(TyOrEx);
+ return CreateSizeOfAlignOfExpr(ArgTy, OpLoc, isSizeof, ArgRange);
+ }
+
+ // Get the end location.
+ Expr *ArgEx = (Expr *)TyOrEx;
+ Action::OwningExprResult Result
+ = CreateSizeOfAlignOfExpr(ArgEx, OpLoc, isSizeof, ArgEx->getSourceRange());
- // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
- return Owned(new (Context) SizeOfAlignOfExpr(isSizeof, isType, TyOrEx,
- Context.getSizeType(), OpLoc,
- Range.getEnd()));
+ if (Result.isInvalid())
+ DeleteExpr(ArgEx);
+
+ return move(Result);
}
QualType Sema::CheckRealImagOperand(Expr *&V, SourceLocation Loc, bool isReal) {
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=66947&r1=66946&r2=66947&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Fri Mar 13 16:01:28 2009
@@ -122,6 +122,13 @@
SourceLocation TyBeginLoc = TypeRange.getBegin();
SourceRange FullRange = SourceRange(TyBeginLoc, RParenLoc);
+ if (Ty->isDependentType() ||
+ CallExpr::hasAnyTypeDependentArguments(Exprs, NumExprs)) {
+ return new (Context) CXXTemporaryObjectExpr(0, Ty, TyBeginLoc,
+ Exprs, NumExprs, RParenLoc);
+ }
+
+
// C++ [expr.type.conv]p1:
// If the expression list is a single expression, the type conversion
// expression is equivalent (in definedness, and if defined in meaning) to the
@@ -134,8 +141,6 @@
TyBeginLoc, Exprs[0], RParenLoc);
}
- // FIXME: What AST node to create when the type is dependent?
-
if (const RecordType *RT = Ty->getAsRecordType()) {
CXXRecordDecl *Record = cast<CXXRecordDecl>(RT->getDecl());
Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=66947&r1=66946&r2=66947&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Fri Mar 13 16:01:28 2009
@@ -1392,6 +1392,9 @@
IsAcceptableNonMemberOperatorCandidate(FunctionDecl *Fn,
QualType T1, QualType T2,
ASTContext &Context) {
+ if (T1->isDependentType() || (!T2.isNull() && T2->isDependentType()))
+ return true;
+
if (T1->isRecordType() || (!T2.isNull() && T2->isRecordType()))
return true;
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=66947&r1=66946&r2=66947&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Mar 13 16:01:28 2009
@@ -1275,7 +1275,14 @@
QualType IntegerType = Context.getCanonicalType(ParamType);
if (const EnumType *Enum = IntegerType->getAsEnumType())
IntegerType = Enum->getDecl()->getIntegerType();
-
+
+ if (Arg->isValueDependent()) {
+ // The argument is value-dependent. Create a new
+ // TemplateArgument with the converted expression.
+ Converted->push_back(TemplateArgument(Arg));
+ return false;
+ }
+
llvm::APInt CanonicalArg(Context.getTypeSize(IntegerType), 0,
IntegerType->isSignedIntegerType());
CanonicalArg = Value;
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=66947&r1=66946&r2=66947&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Fri Mar 13 16:01:28 2009
@@ -17,6 +17,7 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Parse/DeclSpec.h"
+#include "clang/Lex/Preprocessor.h" // for the identifier table
#include "clang/Basic/LangOptions.h"
#include "llvm/Support/Compiler.h"
@@ -441,7 +442,12 @@
break;
case TemplateArgument::Expression:
- assert(false && "Cannot instantiate expressions yet");
+ Sema::OwningExprResult E
+ = SemaRef.InstantiateExpr(Arg->getAsExpr(), TemplateArgs,
+ NumTemplateArgs);
+ if (E.isInvalid())
+ return QualType();
+ InstantiatedTemplateArgs.push_back((Expr *)E.release());
break;
}
}
@@ -564,6 +570,8 @@
unsigned NumTemplateArgs;
public:
+ typedef Sema::OwningExprResult OwningExprResult;
+
TemplateExprInstantiator(Sema &SemaRef,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs)
@@ -573,11 +581,13 @@
// FIXME: Once we get closer to completion, replace these
// manually-written declarations with automatically-generated ones
// from clang/AST/StmtNodes.def.
- Sema::OwningExprResult VisitIntegerLiteral(IntegerLiteral *E);
- Sema::OwningExprResult VisitDeclRefExpr(DeclRefExpr *E);
- Sema::OwningExprResult VisitParenExpr(ParenExpr *E);
- Sema::OwningExprResult VisitBinaryOperator(BinaryOperator *E);
- Sema::OwningExprResult VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
+ OwningExprResult VisitIntegerLiteral(IntegerLiteral *E);
+ OwningExprResult VisitDeclRefExpr(DeclRefExpr *E);
+ OwningExprResult VisitParenExpr(ParenExpr *E);
+ OwningExprResult VisitBinaryOperator(BinaryOperator *E);
+ OwningExprResult VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
+ OwningExprResult VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
+ OwningExprResult VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E);
// Base case. I'm supposed to ignore this.
Sema::OwningExprResult VisitStmt(Stmt *) {
@@ -692,6 +702,9 @@
DeclRefExpr *DRE = cast<DeclRefExpr>(E->getCallee());
OverloadedFunctionDecl *Overloads
= cast<OverloadedFunctionDecl>(DRE->getDecl());
+
+ // FIXME: Do we have to check
+ // IsAcceptableNonMemberOperatorCandidate for each of these?
for (OverloadedFunctionDecl::function_iterator
F = Overloads->function_begin(),
FEnd = Overloads->function_end();
@@ -717,6 +730,90 @@
}
Sema::OwningExprResult
+TemplateExprInstantiator::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
+ bool isSizeOf = E->isSizeOf();
+
+ if (E->isArgumentType()) {
+ QualType T = E->getArgumentType();
+ if (T->isDependentType()) {
+ T = SemaRef.InstantiateType(T, TemplateArgs, NumTemplateArgs,
+ /*FIXME*/E->getOperatorLoc(),
+ &SemaRef.PP.getIdentifierTable().get("sizeof"));
+ if (T.isNull())
+ return SemaRef.ExprError();
+ }
+
+ return SemaRef.CreateSizeOfAlignOfExpr(T, E->getOperatorLoc(), isSizeOf,
+ E->getSourceRange());
+ }
+
+ Sema::OwningExprResult Arg = Visit(E->getArgumentExpr());
+ if (Arg.isInvalid())
+ return SemaRef.ExprError();
+
+ Sema::OwningExprResult Result
+ = SemaRef.CreateSizeOfAlignOfExpr((Expr *)Arg.get(), E->getOperatorLoc(),
+ isSizeOf, E->getSourceRange());
+ if (Result.isInvalid())
+ return SemaRef.ExprError();
+
+ Arg.release();
+ return move(Result);
+}
+
+Sema::OwningExprResult
+TemplateExprInstantiator::VisitCXXTemporaryObjectExpr(
+ CXXTemporaryObjectExpr *E) {
+ QualType T = E->getType();
+ if (T->isDependentType()) {
+ T = SemaRef.InstantiateType(T, TemplateArgs, NumTemplateArgs,
+ E->getTypeBeginLoc(), DeclarationName());
+ if (T.isNull())
+ return SemaRef.ExprError();
+ }
+
+ llvm::SmallVector<Expr *, 16> Args;
+ Args.reserve(E->getNumArgs());
+ bool Invalid = false;
+ for (CXXTemporaryObjectExpr::arg_iterator Arg = E->arg_begin(),
+ ArgEnd = E->arg_end();
+ Arg != ArgEnd; ++Arg) {
+ OwningExprResult InstantiatedArg = Visit(*Arg);
+ if (InstantiatedArg.isInvalid()) {
+ Invalid = true;
+ break;
+ }
+
+ Args.push_back((Expr *)InstantiatedArg.release());
+ }
+
+ if (!Invalid) {
+ SourceLocation CommaLoc;
+ // FIXME: HACK!
+ if (Args.size() > 1)
+ CommaLoc
+ = SemaRef.PP.getLocForEndOfToken(Args[0]->getSourceRange().getEnd());
+ Sema::ExprResult Result
+ = SemaRef.ActOnCXXTypeConstructExpr(SourceRange(E->getTypeBeginLoc()
+ /*, FIXME*/),
+ T.getAsOpaquePtr(),
+ /*FIXME*/E->getTypeBeginLoc(),
+ (void**)&Args[0], Args.size(),
+ /*HACK*/&CommaLoc,
+ E->getSourceRange().getEnd());
+ if (!Result.isInvalid())
+ return SemaRef.Owned(Result);
+ }
+
+ // Clean up the instantiated arguments.
+ // FIXME: Would rather do this with RAII.
+ for (unsigned Idx = 0; Idx < Args.size(); ++Idx)
+ SemaRef.DeleteExpr(Args[Idx]);
+
+ return SemaRef.ExprError();
+}
+
+Sema::OwningExprResult
Sema::InstantiateExpr(Expr *E, const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs) {
TemplateExprInstantiator Instantiator(*this, TemplateArgs, NumTemplateArgs);
Modified: cfe/trunk/test/SemaTemplate/instantiate-expr-1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-expr-1.cpp?rev=66947&r1=66946&r2=66947&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-expr-1.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-expr-1.cpp Fri Mar 13 16:01:28 2009
@@ -43,3 +43,13 @@
(void)sizeof(BitfieldDivide<5, 1>);
(void)sizeof(BitfieldDivide<5, 0>); // expected-note{{in instantiation of template class 'struct BitfieldDivide<5, 0>' requested here}}
}
+
+template<typename T, T I, int J>
+struct BitfieldDep {
+ int bitfield : I + J;
+};
+
+void test_BitfieldDep() {
+ (void)sizeof(BitfieldDep<int, 1, 5>);
+}
+
More information about the cfe-commits
mailing list