[cfe-commits] r101549 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaCXXCast.cpp lib/Sema/SemaChecking.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaInit.cpp lib/Sema/SemaInit.h lib/Sema/SemaStmt.cpp test/SemaTemplate/instantiate-expr-2.cpp

Douglas Gregor dgregor at apple.com
Fri Apr 16 15:09:46 PDT 2010


Author: dgregor
Date: Fri Apr 16 17:09:46 2010
New Revision: 101549

URL: http://llvm.org/viewvc/llvm-project?rev=101549&view=rev
Log:
Collapse the three separate initialization paths in
TryStaticImplicitCast (for references, class types, and everything
else, respectively) into a single invocation of
InitializationSequence.

One of the paths (for class types) was the only client of
Sema::TryInitializationByConstructor, which I have eliminated. This
also simplified the interface for much of the cast-checking logic,
eliminating yet more code.

I've kept the representation of C++ functional casts with <> 1
arguments the same, despite the fact that I hate it. That fix will
come soon. To satisfy my paranoia, I've bootstrapped + tested Clang
with these changes.


Modified:
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaCXXCast.cpp
    cfe/trunk/lib/Sema/SemaChecking.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/lib/Sema/SemaInit.h
    cfe/trunk/lib/Sema/SemaStmt.cpp
    cfe/trunk/test/SemaTemplate/instantiate-expr-2.cpp

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=101549&r1=101548&r2=101549&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Fri Apr 16 17:09:46 2010
@@ -2161,12 +2161,6 @@
   /// it simply returns the passed in expression.
   OwningExprResult MaybeBindToTemporary(Expr *E);
 
-  CXXConstructorDecl *
-  TryInitializationByConstructor(QualType ClassType,
-                                 Expr **Args, unsigned NumArgs,
-                                 SourceLocation Loc,
-                                 InitializationKind Kind);
-
   bool CompleteConstructorCall(CXXConstructorDecl *Constructor,
                                MultiExprArg ArgsPtr,
                                SourceLocation Loc,                                    
@@ -4206,7 +4200,6 @@
   /// C semantics, or forward to CXXCheckCStyleCast in C++.
   bool CheckCastTypes(SourceRange TyRange, QualType CastTy, Expr *&CastExpr,
                       CastExpr::CastKind &Kind,
-                      CXXMethodDecl *& ConversionDecl,
                       bool FunctionalStyle = false);
 
   // CheckVectorCast - check type constraints for vectors.
@@ -4227,8 +4220,7 @@
   /// CXXCheckCStyleCast - Check constraints of a C-style or function-style
   /// cast under C++ semantics.
   bool CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr,
-                          CastExpr::CastKind &Kind, bool FunctionalStyle,
-                          CXXMethodDecl *&ConversionDecl);
+                          CastExpr::CastKind &Kind, bool FunctionalStyle);
 
   /// CheckMessageArgumentTypes - Check types in an Obj-C message send.
   /// \param Method - May be null.

Modified: cfe/trunk/lib/Sema/SemaCXXCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXCast.cpp?rev=101549&r1=101548&r2=101549&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXCast.cpp Fri Apr 16 17:09:46 2010
@@ -46,8 +46,7 @@
                                  CastExpr::CastKind &Kind);
 static void CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
                             const SourceRange &OpRange,
-                            CastExpr::CastKind &Kind,
-                            CXXMethodDecl *&ConversionDecl);
+                            CastExpr::CastKind &Kind);
 static void CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
                              const SourceRange &OpRange,
                              const SourceRange &DestRange,
@@ -94,14 +93,12 @@
                                            QualType DestType, bool CStyle,
                                            const SourceRange &OpRange,
                                            unsigned &msg,
-                                           CastExpr::CastKind &Kind,
-                                           CXXMethodDecl *&ConversionDecl);
+                                           CastExpr::CastKind &Kind);
 static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
                                    QualType DestType, bool CStyle,
                                    const SourceRange &OpRange,
                                    unsigned &msg,
-                                   CastExpr::CastKind &Kind,
-                                   CXXMethodDecl *&ConversionDecl);
+                                   CastExpr::CastKind &Kind);
 static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
                                   bool CStyle, unsigned &msg);
 static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
@@ -168,21 +165,8 @@
   }
   case tok::kw_static_cast: {
     CastExpr::CastKind Kind = CastExpr::CK_Unknown;
-    if (!TypeDependent) {
-      CXXMethodDecl *Method = 0;
-      
-      CheckStaticCast(*this, Ex, DestType, OpRange, Kind, Method);
-      
-      if (Method) {
-        OwningExprResult CastArg 
-          = BuildCXXCastArgument(OpLoc, DestType.getNonReferenceType(), 
-                                 Kind, Method, Owned(Ex));
-          if (CastArg.isInvalid())
-            return ExprError();
-          
-          Ex = CastArg.takeAs<Expr>();
-      }
-    }
+    if (!TypeDependent)
+      CheckStaticCast(*this, Ex, DestType, OpRange, Kind);
     
     return Owned(new (Context) CXXStaticCastExpr(DestType.getNonReferenceType(),
                                                  Kind, Ex, DestTInfo, OpLoc));
@@ -447,8 +431,7 @@
 /// implicit conversions explicit and getting rid of data loss warnings.
 void
 CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
-                const SourceRange &OpRange, CastExpr::CastKind &Kind,
-                CXXMethodDecl *&ConversionDecl) {
+                const SourceRange &OpRange, CastExpr::CastKind &Kind) {
   // This test is outside everything else because it's the only case where
   // a non-lvalue-reference target type does not lead to decay.
   // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
@@ -462,7 +445,7 @@
 
   unsigned msg = diag::err_bad_cxx_cast_generic;
   if (TryStaticCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange, msg,
-                    Kind, ConversionDecl)
+                    Kind)
       != TC_Success && msg != 0)
     Self.Diag(OpRange.getBegin(), msg) << CT_Static
       << SrcExpr->getType() << DestType << OpRange;
@@ -474,8 +457,7 @@
 static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
                                    QualType DestType, bool CStyle,
                                    const SourceRange &OpRange, unsigned &msg,
-                                   CastExpr::CastKind &Kind,
-                                   CXXMethodDecl *&ConversionDecl) {
+                                   CastExpr::CastKind &Kind) {
   // The order the tests is not entirely arbitrary. There is one conversion
   // that can be handled in two different ways. Given:
   // struct A {};
@@ -512,7 +494,7 @@
   // C++ 5.2.9p2: An expression e can be explicitly converted to a type T
   //   [...] if the declaration "T t(e);" is well-formed, [...].
   tcr = TryStaticImplicitCast(Self, SrcExpr, DestType, CStyle, OpRange, msg,
-                              Kind, ConversionDecl);
+                              Kind);
   if (tcr != TC_NotApplicable)
     return tcr;
   
@@ -900,8 +882,7 @@
 TryCastResult
 TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
                       bool CStyle, const SourceRange &OpRange, unsigned &msg,
-                      CastExpr::CastKind &Kind, 
-                      CXXMethodDecl *&ConversionDecl) {
+                      CastExpr::CastKind &Kind) {
   if (DestType->isRecordType()) {
     if (Self.RequireCompleteType(OpRange.getBegin(), DestType,
                                  diag::err_bad_dynamic_cast_incomplete)) {
@@ -909,66 +890,33 @@
       return TC_Failed;
     }
   }
-
-  if (DestType->isReferenceType()) {
-    // All reference bindings insert implicit casts above that do the actual
-    // casting.
-    Kind = CastExpr::CK_NoOp;
-
-    // At this point of CheckStaticCast, if the destination is a reference,
-    // this has to work. There is no other way that works.
-    // On the other hand, if we're checking a C-style cast, we've still got
-    // the reinterpret_cast way.
-    InitializedEntity Entity = InitializedEntity::InitializeTemporary(DestType);
-    InitializationKind InitKind = InitializationKind::CreateCast(OpRange, 
-                                                                 CStyle);    
-    InitializationSequence InitSeq(Self, Entity, InitKind, &SrcExpr, 1);
-    if (InitSeq.getKind() == InitializationSequence::FailedSequence && CStyle)
-      return TC_NotApplicable;
-    
-    Sema::OwningExprResult Result
-      = InitSeq.Perform(Self, Entity, InitKind,
-                        Action::MultiExprArg(Self, (void**)&SrcExpr, 1));
-    if (Result.isInvalid()) {
-      msg = 0;
-      return TC_Failed;
-    }
-    
-    SrcExpr = Result.takeAs<Expr>();
-    return TC_Success;
-  }
-
-  if (DestType->isRecordType()) {
-    if (CXXConstructorDecl *Constructor
-          = Self.TryInitializationByConstructor(DestType, &SrcExpr, 1,
-                                                OpRange.getBegin(),
-              InitializationKind::CreateDirect(OpRange.getBegin(),
-                                               OpRange.getBegin(), 
-                                               OpRange.getEnd()))) {
-      ConversionDecl = Constructor;
-      Kind = CastExpr::CK_ConstructorConversion;
-      return TC_Success;
-    }
-    
-    return TC_NotApplicable;
-  }
-
+  
+  // At this point of CheckStaticCast, if the destination is a reference,
+  // this has to work. There is no other way that works.
+  // On the other hand, if we're checking a C-style cast, we've still got
+  // the reinterpret_cast way.
   InitializedEntity Entity = InitializedEntity::InitializeTemporary(DestType);
   InitializationKind InitKind
-    = InitializationKind::CreateCast(/*FIXME:*/OpRange, CStyle);
+    = InitializationKind::CreateCast(/*FIXME:*/OpRange, 
+                                                               CStyle);    
   InitializationSequence InitSeq(Self, Entity, InitKind, &SrcExpr, 1);
-  if (InitSeq.getKind() == InitializationSequence::FailedSequence)
+  if (InitSeq.getKind() == InitializationSequence::FailedSequence && 
+      (CStyle || !DestType->isReferenceType()))
     return TC_NotApplicable;
-
+    
   Sema::OwningExprResult Result
-    = InitSeq.Perform(Self, Entity, InitKind, 
-                      Action::MultiExprArg(Self, (void **)&SrcExpr, 1));
-  Kind = CastExpr::CK_NoOp;
+    = InitSeq.Perform(Self, Entity, InitKind,
+                      Action::MultiExprArg(Self, (void**)&SrcExpr, 1));
   if (Result.isInvalid()) {
     msg = 0;
     return TC_Failed;
   }
   
+  if (InitSeq.isConstructorInitialization())
+    Kind = CastExpr::CK_ConstructorConversion;
+  else
+    Kind = CastExpr::CK_NoOp;
+  
   SrcExpr = Result.takeAs<Expr>();
   return TC_Success;
 }
@@ -1234,8 +1182,7 @@
 }
 
 bool Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr,
-                              CastExpr::CastKind &Kind, bool FunctionalStyle,
-                              CXXMethodDecl *&ConversionDecl) {
+                              CastExpr::CastKind &Kind, bool FunctionalStyle) {
   // This test is outside everything else because it's the only case where
   // a non-lvalue-reference target type does not lead to decay.
   // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
@@ -1270,8 +1217,7 @@
 
   if (tcr == TC_NotApplicable) {
     // ... or if that is not possible, a static_cast, ignoring const, ...
-    tcr = TryStaticCast(*this, CastExpr, CastTy, /*CStyle*/true, R, msg,
-                        Kind, ConversionDecl);
+    tcr = TryStaticCast(*this, CastExpr, CastTy, /*CStyle*/true, R, msg, Kind);
     if (tcr == TC_NotApplicable) {
       // ... and finally a reinterpret_cast, ignoring const.
       tcr = TryReinterpretCast(*this, CastExpr, CastTy, /*CStyle*/true, R, msg,

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=101549&r1=101548&r2=101549&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Fri Apr 16 17:09:46 2010
@@ -409,9 +409,7 @@
     // GCC does an implicit conversion to the pointer or integer ValType.  This
     // can fail in some cases (1i -> int**), check for this error case now.
     CastExpr::CastKind Kind = CastExpr::CK_Unknown;
-    CXXMethodDecl *ConversionDecl = 0;
-    if (CheckCastTypes(Arg->getSourceRange(), ValType, Arg, Kind,
-                       ConversionDecl))
+    if (CheckCastTypes(Arg->getSourceRange(), ValType, Arg, Kind))
       return true;
 
     // Okay, we have something that *can* be converted to the right type.  Check

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=101549&r1=101548&r2=101549&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Apr 16 17:09:46 2010
@@ -4271,113 +4271,6 @@
     FinalizeVarWithDestructor(VDecl, Record);
 }
 
-/// \brief Add the applicable constructor candidates for an initialization
-/// by constructor.
-static void AddConstructorInitializationCandidates(Sema &SemaRef,
-                                                   QualType ClassType,
-                                                   Expr **Args,
-                                                   unsigned NumArgs,
-                                                   InitializationKind Kind,
-                                           OverloadCandidateSet &CandidateSet) {
-  // C++ [dcl.init]p14:
-  //   If the initialization is direct-initialization, or if it is
-  //   copy-initialization where the cv-unqualified version of the
-  //   source type is the same class as, or a derived class of, the
-  //   class of the destination, constructors are considered. The
-  //   applicable constructors are enumerated (13.3.1.3), and the
-  //   best one is chosen through overload resolution (13.3). The
-  //   constructor so selected is called to initialize the object,
-  //   with the initializer expression(s) as its argument(s). If no
-  //   constructor applies, or the overload resolution is ambiguous,
-  //   the initialization is ill-formed.
-  const RecordType *ClassRec = ClassType->getAs<RecordType>();
-  assert(ClassRec && "Can only initialize a class type here");
-  
-  // FIXME: When we decide not to synthesize the implicitly-declared
-  // constructors, we'll need to make them appear here.
-
-  const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(ClassRec->getDecl());
-  DeclarationName ConstructorName
-    = SemaRef.Context.DeclarationNames.getCXXConstructorName(
-              SemaRef.Context.getCanonicalType(ClassType).getUnqualifiedType());
-  DeclContext::lookup_const_iterator Con, ConEnd;
-  for (llvm::tie(Con, ConEnd) = ClassDecl->lookup(ConstructorName);
-       Con != ConEnd; ++Con) {
-    DeclAccessPair FoundDecl = DeclAccessPair::make(*Con, (*Con)->getAccess());
-
-    // Find the constructor (which may be a template).
-    CXXConstructorDecl *Constructor = 0;
-    FunctionTemplateDecl *ConstructorTmpl= dyn_cast<FunctionTemplateDecl>(*Con);
-    if (ConstructorTmpl)
-      Constructor
-      = cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl());
-    else
-      Constructor = cast<CXXConstructorDecl>(*Con);
-    
-    if ((Kind.getKind() == InitializationKind::IK_Direct) ||
-        (Kind.getKind() == InitializationKind::IK_Value) ||
-        (Kind.getKind() == InitializationKind::IK_Copy &&
-         Constructor->isConvertingConstructor(/*AllowExplicit=*/false)) ||
-        ((Kind.getKind() == InitializationKind::IK_Default) && 
-         Constructor->isDefaultConstructor())) {
-      if (ConstructorTmpl)
-        SemaRef.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
-                                             /*ExplicitArgs*/ 0,
-                                             Args, NumArgs, CandidateSet);
-      else
-        SemaRef.AddOverloadCandidate(Constructor, FoundDecl,
-                                     Args, NumArgs, CandidateSet);
-    }
-  }
-}
-
-/// \brief Attempt to perform initialization by constructor 
-/// (C++ [dcl.init]p14), which may occur as part of direct-initialization or 
-/// copy-initialization. 
-///
-/// This routine determines whether initialization by constructor is possible,
-/// but it does not emit any diagnostics in the case where the initialization
-/// is ill-formed.
-///
-/// \param ClassType the type of the object being initialized, which must have
-/// class type.
-///
-/// \param Args the arguments provided to initialize the object
-///
-/// \param NumArgs the number of arguments provided to initialize the object
-///
-/// \param Kind the type of initialization being performed
-///
-/// \returns the constructor used to initialize the object, if successful.
-/// Otherwise, emits a diagnostic and returns NULL.
-CXXConstructorDecl *
-Sema::TryInitializationByConstructor(QualType ClassType,
-                                     Expr **Args, unsigned NumArgs,
-                                     SourceLocation Loc,
-                                     InitializationKind Kind) {
-  // Build the overload candidate set
-  OverloadCandidateSet CandidateSet(Loc);
-  AddConstructorInitializationCandidates(*this, ClassType, Args, NumArgs, Kind,
-                                         CandidateSet);
-  
-  // Determine whether we found a constructor we can use.
-  OverloadCandidateSet::iterator Best;
-  switch (BestViableFunction(CandidateSet, Loc, Best)) {
-    case OR_Success:
-    case OR_Deleted:
-      // We found a constructor. Return it.
-      return cast<CXXConstructorDecl>(Best->Function);
-      
-    case OR_No_Viable_Function:
-    case OR_Ambiguous:
-      // Overload resolution failed. Return nothing.
-      return 0;
-  }
-  
-  // Silence GCC warning
-  return 0;
-}
-
 /// \brief Given a constructor and the set of arguments provided for the
 /// constructor, convert the arguments and add any required default arguments
 /// to form a proper call to this constructor.

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=101549&r1=101548&r2=101549&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Apr 16 17:09:46 2010
@@ -3789,11 +3789,9 @@
 /// CheckCastTypes - Check type constraints for casting between types.
 bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,
                           CastExpr::CastKind& Kind,
-                          CXXMethodDecl *& ConversionDecl,
                           bool FunctionalStyle) {
   if (getLangOptions().CPlusPlus)
-    return CXXCheckCStyleCast(TyR, castType, castExpr, Kind, FunctionalStyle,
-                              ConversionDecl);
+    return CXXCheckCStyleCast(TyR, castType, castExpr, Kind, FunctionalStyle);
 
   DefaultFunctionArrayLvalueConversion(castExpr);
 
@@ -3953,25 +3951,12 @@
                           SourceLocation RParenLoc, ExprArg Op) {
   Expr *castExpr = static_cast<Expr*>(Op.get());
 
-  CXXMethodDecl *Method = 0;
   CastExpr::CastKind Kind = CastExpr::CK_Unknown;
   if (CheckCastTypes(SourceRange(LParenLoc, RParenLoc), Ty->getType(), castExpr,
-                     Kind, Method))
+                     Kind))
     return ExprError();
 
-  if (Method) {
-    // FIXME: preserve type source info here
-    OwningExprResult CastArg = BuildCXXCastArgument(LParenLoc, Ty->getType(),
-                                                    Kind, Method, move(Op));
-
-    if (CastArg.isInvalid())
-      return ExprError();
-
-    castExpr = CastArg.takeAs<Expr>();
-  } else {
-    Op.release();
-  }
-
+  Op.release();
   return Owned(new (Context) CStyleCastExpr(Ty->getType().getNonReferenceType(),
                                             Kind, castExpr, Ty,
                                             LParenLoc, RParenLoc));

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=101549&r1=101548&r2=101549&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Fri Apr 16 17:09:46 2010
@@ -504,21 +504,10 @@
   //
   if (NumExprs == 1) {
     CastExpr::CastKind Kind = CastExpr::CK_Unknown;
-    CXXMethodDecl *Method = 0;
-    if (CheckCastTypes(TypeRange, Ty, Exprs[0], Kind, Method,
-                       /*FunctionalStyle=*/true))
+    if (CheckCastTypes(TypeRange, Ty, Exprs[0], Kind, /*FunctionalStyle=*/true))
       return ExprError();
 
     exprs.release();
-    if (Method) {
-      OwningExprResult CastArg 
-        = BuildCXXCastArgument(TypeRange.getBegin(), Ty.getNonReferenceType(), 
-                               Kind, Method, Owned(Exprs[0]));
-      if (CastArg.isInvalid())
-        return ExprError();
-
-      Exprs[0] = CastArg.takeAs<Expr>();
-    }
 
     return Owned(new (Context) CXXFunctionalCastExpr(Ty.getNonReferenceType(),
                                                      TInfo, TyBeginLoc, Kind,

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=101549&r1=101548&r2=101549&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Fri Apr 16 17:09:46 2010
@@ -2036,6 +2036,10 @@
   return false;
 }
 
+bool InitializationSequence::isConstructorInitialization() const {
+  return !Steps.empty() && Steps.back().Kind == SK_ConstructorInitialization;
+}
+
 void InitializationSequence::AddAddressOverloadResolutionStep(
                                                       FunctionDecl *Function,
                                                       DeclAccessPair Found) {
@@ -3510,6 +3514,7 @@
     }
 
     case SK_ConstructorInitialization: {
+      unsigned NumArgs = Args.size();
       CXXConstructorDecl *Constructor
         = cast<CXXConstructorDecl>(Step->Function.Function);
 
@@ -3523,8 +3528,9 @@
                                     Loc, ConstructorArgs))
         return S.ExprError();
           
-      // Build the an expression that constructs a temporary.
+      // Build the expression that constructs a temporary.
       if (Entity.getKind() == InitializedEntity::EK_Temporary &&
+          NumArgs != 1 && // FIXME: Hack to work around cast weirdness
           (Kind.getKind() == InitializationKind::IK_Direct ||
            Kind.getKind() == InitializationKind::IK_Value)) {
         // An explicitly-constructed temporary, e.g., X(1, 2).

Modified: cfe/trunk/lib/Sema/SemaInit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.h?rev=101549&r1=101548&r2=101549&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.h (original)
+++ cfe/trunk/lib/Sema/SemaInit.h Fri Apr 16 17:09:46 2010
@@ -606,6 +606,10 @@
   /// \brief Determine whether this initialization failed due to an ambiguity.
   bool isAmbiguous() const;
   
+  /// \brief Determine whether this initialization is direct call to a 
+  /// constructor.
+  bool isConstructorInitialization() const;
+  
   /// \brief Add a new step in the initialization that resolves the address
   /// of an overloaded function to a specific function declaration.
   ///

Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=101549&r1=101548&r2=101549&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Fri Apr 16 17:09:46 2010
@@ -126,8 +126,12 @@
       Diag(Loc, diag::warn_unused_call) << R1 << R2 << "warn_unused_result";
       return;
     }
+  } else if (const CXXFunctionalCastExpr *FC
+                                       = dyn_cast<CXXFunctionalCastExpr>(E)) {
+    if (isa<CXXConstructExpr>(FC->getSubExpr()) ||
+        isa<CXXTemporaryObjectExpr>(FC->getSubExpr()))
+      return;
   }
-
   // Diagnose "(void*) blah" as a typo for "(void) blah".
   else if (const CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(E)) {
     TypeSourceInfo *TI = CE->getTypeInfoAsWritten();

Modified: cfe/trunk/test/SemaTemplate/instantiate-expr-2.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-expr-2.cpp?rev=101549&r1=101548&r2=101549&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-expr-2.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-expr-2.cpp Fri Apr 16 17:09:46 2010
@@ -193,3 +193,22 @@
 
   void f0(int **a) { C::f0(a); }
 }
+
+namespace N13 {
+  class A{
+    A(const A&);
+
+  public:
+    ~A();
+    A(int);
+    template<typename T> A &operator<<(const T&);
+  };
+
+  template<typename T>
+  void f(T t) {
+    A(17) << t;
+  }
+
+  template void f(int);
+
+}





More information about the cfe-commits mailing list