[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