[cfe-commits] r141170 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/SemaCXXCast.cpp lib/Sema/SemaChecking.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp

John McCall rjmccall at apple.com
Wed Oct 5 00:41:45 PDT 2011


Author: rjmccall
Date: Wed Oct  5 02:41:44 2011
New Revision: 141170

URL: http://llvm.org/viewvc/llvm-project?rev=141170&view=rev
Log:
Refactor the analysis of C++ cast expressions so that even
C-style and functional casts are built in SemaCXXCast.cpp.
Introduce a helper class to encapsulate most of the random
state being passed around, at least one level down.


Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaCXXCast.cpp
    cfe/trunk/lib/Sema/SemaChecking.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=141170&r1=141169&r2=141170&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Oct  5 02:41:44 2011
@@ -5754,12 +5754,10 @@
                                                       bool &ObjCConversion,
                                                 bool &ObjCLifetimeConversion);
 
-  /// CheckCastTypes - Check type constraints for casting between types under
-  /// C semantics, or forward to CXXCheckCStyleCast in C++.
-  ExprResult CheckCastTypes(SourceLocation CastStartLoc, SourceRange TypeRange, 
-                            QualType CastType, Expr *CastExpr, CastKind &Kind, 
-                            ExprValueKind &VK, CXXCastPath &BasePath,
-                            bool FunctionalStyle = false);
+  /// CheckCCastTypes - Check type constraints for casting between
+  /// types under C semantics.
+  ExprResult CheckCCastTypes(SourceLocation CastStartLoc, SourceRange TypeRange, 
+                             QualType CastType, Expr *CastExpr, CastKind &Kind);
 
   ExprResult checkUnknownAnyCast(SourceRange TypeRange, QualType CastType,
                                  Expr *CastExpr, CastKind &CastKind,
@@ -5780,12 +5778,17 @@
   ExprResult CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *CastExpr,
                                 CastKind &Kind);
 
-  /// CXXCheckCStyleCast - Check constraints of a C-style or function-style
+  /// CXXBuildCStyleCastExpr - Check constraints of a C-style or function-style
   /// cast under C++ semantics.
-  ExprResult CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK,
-                                Expr *CastExpr, CastKind &Kind,
-                                CXXCastPath &BasePath, bool FunctionalStyle);
-    
+  ExprResult CXXBuildCStyleCastExpr(SourceLocation LParenLoc,
+                                    TypeSourceInfo *TInfo,
+                                    SourceLocation RParenLoc,
+                                    Expr *CastExpr);
+  ExprResult BuildCXXFunctionalCastExpr(TypeSourceInfo *TInfo,
+                                        SourceLocation LParenLoc,
+                                        Expr *CastExpr,
+                                        SourceLocation RParenLoc);
+
   /// \brief Checks for invalid conversions and casts between
   /// retainable pointers and other pointer kinds.
   void CheckObjCARCConversion(SourceRange castRange, QualType castType, 

Modified: cfe/trunk/lib/Sema/SemaCXXCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXCast.cpp?rev=141170&r1=141169&r2=141170&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXCast.cpp Wed Oct  5 02:41:44 2011
@@ -39,29 +39,43 @@
   CT_Functional   ///< Type(expr)
 };
 
+namespace {
+  struct CastOperation {
+    CastOperation(Sema &S, QualType destType, ExprResult src)
+      : Self(S), SrcExpr(src), DestType(destType),
+        ResultType(destType.getNonLValueExprType(S.Context)),
+        ValueKind(Expr::getValueKindForType(destType)),
+        Kind(CK_Dependent), IsARCUnbridgedCast(false) {}
+
+    Sema &Self;
+    ExprResult SrcExpr;
+    QualType DestType;
+    QualType ResultType;
+    ExprValueKind ValueKind;
+    CastKind Kind;
+    bool IsARCUnbridgedCast;
+    CXXCastPath BasePath;
 
+    SourceRange OpRange;
+    SourceRange DestRange;
 
+    void CheckConstCast();
+    void CheckReinterpretCast();
+    void CheckStaticCast();
+    void CheckDynamicCast();
+    void CheckCStyleCast(bool FunctionalCast);
 
-static void CheckConstCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
-                           ExprValueKind &VK,
-                           const SourceRange &OpRange,
-                           const SourceRange &DestRange);
-static void CheckReinterpretCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
-                                 ExprValueKind &VK,
-                                 const SourceRange &OpRange,
-                                 const SourceRange &DestRange,
-                                 CastKind &Kind);
-static void CheckStaticCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
-                            ExprValueKind &VK,
-                            const SourceRange &OpRange,
-                            CastKind &Kind,
-                            CXXCastPath &BasePath);
-static void CheckDynamicCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
-                             ExprValueKind &VK,
-                             const SourceRange &OpRange,
-                             const SourceRange &DestRange,
-                             CastKind &Kind,
-                             CXXCastPath &BasePath);
+    void checkCastAlign() {
+      Self.CheckCastAlign(SrcExpr.get(), DestType, OpRange);
+    }
+
+    void checkObjCARCConversion(Sema::CheckedConversionKind CCK) {
+      Expr *src = SrcExpr.get();
+      Self.CheckObjCARCConversion(OpRange, DestType, src, CCK);
+      SrcExpr = src;
+    }
+  };
+}
 
 static bool CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType,
                                bool CheckCVR, bool CheckObjCLifetime);
@@ -162,70 +176,61 @@
   ExprResult Ex = Owned(E);
   QualType DestType = DestTInfo->getType();
 
-  SourceRange OpRange(OpLoc, Parens.getEnd());
-  SourceRange DestRange = AngleBrackets;
-
   // If the type is dependent, we won't do the semantic analysis now.
   // FIXME: should we check this in a more fine-grained manner?
   bool TypeDependent = DestType->isDependentType() || Ex.get()->isTypeDependent();
 
-  ExprValueKind VK = VK_RValue;
-  if (TypeDependent)
-    VK = Expr::getValueKindForType(DestType);
+  CastOperation Op(*this, DestType, E);
+  Op.OpRange = SourceRange(OpLoc, Parens.getEnd());
+  Op.DestRange = AngleBrackets;
 
   switch (Kind) {
   default: llvm_unreachable("Unknown C++ cast!");
 
   case tok::kw_const_cast:
     if (!TypeDependent) {
-      CheckConstCast(*this, Ex, DestType, VK, OpRange, DestRange);
-      if (Ex.isInvalid())
+      Op.CheckConstCast();
+      if (Op.SrcExpr.isInvalid())
         return ExprError();
     }
-    return Owned(CXXConstCastExpr::Create(Context,
-                                        DestType.getNonLValueExprType(Context),
-                                          VK, Ex.take(), DestTInfo, OpLoc,
+    return Owned(CXXConstCastExpr::Create(Context, Op.ResultType, Op.ValueKind,
+                                          Op.SrcExpr.take(), DestTInfo, OpLoc,
                                           Parens.getEnd()));
 
   case tok::kw_dynamic_cast: {
-    CastKind Kind = CK_Dependent;
-    CXXCastPath BasePath;
     if (!TypeDependent) {
-      CheckDynamicCast(*this, Ex, DestType, VK, OpRange, DestRange,
-                       Kind, BasePath);
-      if (Ex.isInvalid())
+      Op.CheckDynamicCast();
+      if (Op.SrcExpr.isInvalid())
         return ExprError();
     }
-    return Owned(CXXDynamicCastExpr::Create(Context,
-                                          DestType.getNonLValueExprType(Context),
-                                            VK, Kind, Ex.take(), &BasePath, DestTInfo,
-                                            OpLoc, Parens.getEnd()));
+    return Owned(CXXDynamicCastExpr::Create(Context, Op.ResultType,
+                                            Op.ValueKind, Op.Kind,
+                                            Op.SrcExpr.take(), &Op.BasePath,
+                                            DestTInfo, OpLoc, Parens.getEnd()));
   }
   case tok::kw_reinterpret_cast: {
-    CastKind Kind = CK_Dependent;
     if (!TypeDependent) {
-      CheckReinterpretCast(*this, Ex, DestType, VK, OpRange, DestRange, Kind);
-      if (Ex.isInvalid())
+      Op.CheckReinterpretCast();
+      if (Op.SrcExpr.isInvalid())
         return ExprError();
     }
-    return Owned(CXXReinterpretCastExpr::Create(Context,
-                                  DestType.getNonLValueExprType(Context),
-                                  VK, Kind, Ex.take(), 0,
-                                  DestTInfo, OpLoc, Parens.getEnd()));
+    return Owned(CXXReinterpretCastExpr::Create(Context, Op.ResultType,
+                                                Op.ValueKind, Op.Kind,
+                                                Op.SrcExpr.take(), 0,
+                                                DestTInfo, OpLoc,
+                                                Parens.getEnd()));
   }
   case tok::kw_static_cast: {
-    CastKind Kind = CK_Dependent;
-    CXXCastPath BasePath;
     if (!TypeDependent) {
-      CheckStaticCast(*this, Ex, DestType, VK, OpRange, Kind, BasePath);
-      if (Ex.isInvalid())
+      Op.CheckStaticCast();
+      if (Op.SrcExpr.isInvalid())
         return ExprError();
     }
     
-    return Owned(CXXStaticCastExpr::Create(Context,
-                                         DestType.getNonLValueExprType(Context),
-                                           VK, Kind, Ex.take(), &BasePath,
-                                           DestTInfo, OpLoc, Parens.getEnd()));
+    return Owned(CXXStaticCastExpr::Create(Context, Op.ResultType, Op.ValueKind,
+                                           Op.Kind, Op.SrcExpr.take(),
+                                           &Op.BasePath, DestTInfo, OpLoc,
+                                           Parens.getEnd()));
   }
   }
 
@@ -461,13 +466,9 @@
 /// CheckDynamicCast - Check that a dynamic_cast\<DestType\>(SrcExpr) is valid.
 /// Refer to C++ 5.2.7 for details. Dynamic casts are used mostly for runtime-
 /// checked downcasts in class hierarchies.
-static void
-CheckDynamicCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
-                 ExprValueKind &VK, const SourceRange &OpRange,
-                 const SourceRange &DestRange, CastKind &Kind,
-                 CXXCastPath &BasePath) {
-  QualType OrigDestType = DestType, OrigSrcType = SrcExpr.get()->getType();
-  DestType = Self.Context.getCanonicalType(DestType);
+void CastOperation::CheckDynamicCast() {
+  QualType OrigSrcType = SrcExpr.get()->getType();
+  QualType DestType = Self.Context.getCanonicalType(this->DestType);
 
   // C++ 5.2.7p1: T shall be a pointer or reference to a complete class type,
   //   or "pointer to cv void".
@@ -479,12 +480,9 @@
     DestPointee = DestPointer->getPointeeType();
   } else if ((DestReference = DestType->getAs<ReferenceType>())) {
     DestPointee = DestReference->getPointeeType();
-    VK = isa<LValueReferenceType>(DestReference) ? VK_LValue 
-       : isa<RValueReferenceType>(DestReference) ? VK_XValue
-       : VK_RValue;
   } else {
     Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ref_or_ptr)
-      << OrigDestType << DestRange;
+      << this->DestType << DestRange;
     return;
   }
 
@@ -519,7 +517,7 @@
   } else if (DestReference->isLValueReferenceType()) {
     if (!SrcExpr.get()->isLValue()) {
       Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_rvalue)
-        << CT_Dynamic << OrigSrcType << OrigDestType << OpRange;
+        << CT_Dynamic << OrigSrcType << this->DestType << OpRange;
     }
     SrcPointee = SrcType;
   } else {
@@ -547,7 +545,7 @@
   // C++ 5.2.7p1: The dynamic_cast operator shall not cast away constness.
   if (!DestPointee.isAtLeastAsQualifiedAs(SrcPointee)) {
     Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_qualifiers_away)
-      << CT_Dynamic << OrigSrcType << OrigDestType << OpRange;
+      << CT_Dynamic << OrigSrcType << this->DestType << OpRange;
     return;
   }
 
@@ -595,11 +593,8 @@
 /// like this:
 /// const char *str = "literal";
 /// legacy_function(const_cast\<char*\>(str));
-void
-CheckConstCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, ExprValueKind &VK,
-               const SourceRange &OpRange, const SourceRange &DestRange) {
-  VK = Expr::getValueKindForType(DestType);
-  if (VK == VK_RValue) {
+void CastOperation::CheckConstCast() {
+  if (ValueKind == VK_RValue) {
     SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take());
     if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
       return;
@@ -617,12 +612,8 @@
 /// Refer to C++ 5.2.10 for details. reinterpret_cast is typically used in code
 /// like this:
 /// char *bytes = reinterpret_cast\<char*\>(int_ptr);
-void
-CheckReinterpretCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
-                     ExprValueKind &VK, const SourceRange &OpRange,
-                     const SourceRange &DestRange, CastKind &Kind) {
-  VK = Expr::getValueKindForType(DestType);
-  if (VK == VK_RValue) {
+void CastOperation::CheckReinterpretCast() {
+  if (ValueKind == VK_RValue) {
     SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take());
     if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
       return;
@@ -647,10 +638,7 @@
       diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr.get(), DestType);
     }
   } else if (tcr == TC_Success && Self.getLangOptions().ObjCAutoRefCount) {
-    Expr *Exp = SrcExpr.get();
-    // Note that Exp does not change with CCK_OtherCast cast type
-    Self.CheckObjCARCConversion(OpRange, DestType,
-                                Exp, Sema::CCK_OtherCast);
+    checkObjCARCConversion(Sema::CCK_OtherCast);
   }
 }
 
@@ -658,10 +646,7 @@
 /// CheckStaticCast - Check that a static_cast\<DestType\>(SrcExpr) is valid.
 /// Refer to C++ 5.2.9 for details. Static casts are mostly used for making
 /// implicit conversions explicit and getting rid of data loss warnings.
-void
-CheckStaticCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
-                ExprValueKind &VK, const SourceRange &OpRange,
-                CastKind &Kind, CXXCastPath &BasePath) {
+void CastOperation::CheckStaticCast() {
   // 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".
@@ -686,8 +671,7 @@
     return;
   }
 
-  VK = Expr::getValueKindForType(DestType);
-  if (VK == VK_RValue && !DestType->isRecordType()) {
+  if (ValueKind == VK_RValue && !DestType->isRecordType()) {
     SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take());
     if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
       return;
@@ -711,16 +695,12 @@
     }
   } else if (tcr == TC_Success) {
     if (Kind == CK_BitCast)
-      Self.CheckCastAlign(SrcExpr.get(), DestType, OpRange);
-    if (Self.getLangOptions().ObjCAutoRefCount) {
-      Expr *Exp = SrcExpr.get();
-      // Note that Exp does not change with CCK_OtherCast cast type
-      Self.CheckObjCARCConversion(OpRange, DestType,
-                                  Exp, Sema::CCK_OtherCast);
-    }
+      checkCastAlign();
+    if (Self.getLangOptions().ObjCAutoRefCount)
+      checkObjCARCConversion(Sema::CCK_OtherCast);
+  } else if (Kind == CK_BitCast) {
+    checkCastAlign();
   }
-  else if (Kind == CK_BitCast)
-    Self.CheckCastAlign(SrcExpr.get(), DestType, OpRange);
 }
 
 /// TryStaticCast - Check if a static cast can be performed, and do so if
@@ -1686,65 +1666,63 @@
   return TC_Success;
 }                                     
 
-ExprResult
-Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK,
-                         Expr *CastExpr, CastKind &Kind, 
-                         CXXCastPath &BasePath,
-                         bool FunctionalStyle) {
+void CastOperation::CheckCStyleCast(bool FunctionalStyle) {
+  // Check for casts from __unknown_any before anything else.
+  if (SrcExpr.get()->getType() == Self.Context.UnknownAnyTy) {
+     SrcExpr = Self.checkUnknownAnyCast(DestRange, DestType,
+                                        SrcExpr.get(), Kind,
+                                        ValueKind, BasePath);
+     return;
+  }
+
   // 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".
-  if (CastTy->isVoidType()) {
+  if (DestType->isVoidType()) {
     Kind = CK_ToVoid;
 
-    ExprResult CastExprRes = IgnoredValueConversions(CastExpr);    
-    if (CastExprRes.isInvalid())
-      return ExprError();
-    CastExpr = CastExprRes.take();
-
-    if (CastExpr->getType() == Context.BoundMemberTy)
-      return CheckPlaceholderExpr(CastExpr); // will always fail
-
-    if (CastExpr->getType() == Context.OverloadTy) {
-      ExprResult SingleFunctionExpr = 
-        ResolveAndFixSingleFunctionTemplateSpecialization(
-                  CastExpr, /* Decay Function to ptr */ false, 
-                  /* Complain */ true, R, CastTy, 
+    SrcExpr = Self.IgnoredValueConversions(SrcExpr.take());
+    if (SrcExpr.isInvalid())
+      return;
+
+    if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
+      SrcExpr = Self.ResolveAndFixSingleFunctionTemplateSpecialization(
+                  SrcExpr.take(), /* Decay Function to ptr */ false, 
+                  /* Complain */ true, DestRange, DestType,
                   diag::err_bad_cstyle_cast_overload);
-      if (SingleFunctionExpr.isInvalid())
-        return ExprError();
-      CastExpr = SingleFunctionExpr.take();
+      if (SrcExpr.isInvalid())
+        return;
     }
 
-    assert(!CastExpr->getType()->isPlaceholderType());
+    if (SrcExpr.get()->getType() == Self.Context.BoundMemberTy) {
+      Self.CheckPlaceholderExpr(SrcExpr.take()); // will always fail
+      return;
+    }
 
-    return Owned(CastExpr);
-  }
+    assert(!SrcExpr.get()->getType()->isPlaceholderType());
 
-  // Make sure we determine the value kind before we bail out for
-  // dependent types.
-  VK = Expr::getValueKindForType(CastTy);
+    return;
+  }
 
   // If the type is dependent, we won't do any other semantic analysis now.
-  if (CastTy->isDependentType() || CastExpr->isTypeDependent()) {
-    Kind = CK_Dependent;
-    return Owned(CastExpr);
+  if (DestType->isDependentType() || SrcExpr.get()->isTypeDependent()) {
+    assert(Kind == CK_Dependent);
+    return;
   }
 
-  if (VK == VK_RValue && !CastTy->isRecordType()) {
-    ExprResult CastExprRes = DefaultFunctionArrayLvalueConversion(CastExpr);
-    if (CastExprRes.isInvalid())
-      return ExprError();
-    CastExpr = CastExprRes.take();
+  if (ValueKind == VK_RValue && !DestType->isRecordType()) {
+    SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take());
+    if (SrcExpr.isInvalid())
+      return;
   }
 
   // AltiVec vector initialization with a single literal.
-  if (const VectorType *vecTy = CastTy->getAs<VectorType>())
+  if (const VectorType *vecTy = DestType->getAs<VectorType>())
     if (vecTy->getVectorKind() == VectorType::AltiVecVector
-        && (CastExpr->getType()->isIntegerType()
-            || CastExpr->getType()->isFloatingType())) {
+        && (SrcExpr.get()->getType()->isIntegerType()
+            || SrcExpr.get()->getType()->isFloatingType())) {
       Kind = CK_VectorSplat;
-      return Owned(CastExpr);
+      return;
     }
 
   // C++ [expr.cast]p5: The conversions performed by
@@ -1759,8 +1737,8 @@
   //   even if a cast resulting from that interpretation is ill-formed.
   // In plain language, this means trying a const_cast ...
   unsigned msg = diag::err_bad_cxx_cast_generic;
-  TryCastResult tcr = TryConstCast(*this, CastExpr, CastTy, /*CStyle*/true,
-                                   msg);
+  TryCastResult tcr = TryConstCast(Self, SrcExpr.get(), DestType,
+                                   /*CStyle*/true, msg);
   if (tcr == TC_Success)
     Kind = CK_NoOp;
 
@@ -1769,47 +1747,79 @@
                      : Sema::CCK_CStyleCast;
   if (tcr == TC_NotApplicable) {
     // ... or if that is not possible, a static_cast, ignoring const, ...
-    ExprResult CastExprRes = Owned(CastExpr);
-    tcr = TryStaticCast(*this, CastExprRes, CastTy, CCK, R, msg, Kind, 
-                        BasePath);
-    if (CastExprRes.isInvalid())
-      return ExprError();
-    CastExpr = CastExprRes.take();
+    tcr = TryStaticCast(Self, SrcExpr, DestType, CCK, OpRange,
+                        msg, Kind, BasePath);
+    if (SrcExpr.isInvalid())
+      return;
+
     if (tcr == TC_NotApplicable) {
       // ... and finally a reinterpret_cast, ignoring const.
-      CastExprRes = Owned(CastExpr);
-      tcr = TryReinterpretCast(*this, CastExprRes, CastTy, /*CStyle*/true, R,
-                               msg, Kind);
-      if (CastExprRes.isInvalid())
-        return ExprError();
-      CastExpr = CastExprRes.take();
+      tcr = TryReinterpretCast(Self, SrcExpr, DestType, /*CStyle*/true,
+                               OpRange, msg, Kind);
+      if (SrcExpr.isInvalid())
+        return;
     }
   }
 
-  if (getLangOptions().ObjCAutoRefCount && tcr == TC_Success)
-    CheckObjCARCConversion(R, CastTy, CastExpr, CCK);
+  if (Self.getLangOptions().ObjCAutoRefCount && tcr == TC_Success)
+    checkObjCARCConversion(CCK);
 
   if (tcr != TC_Success && msg != 0) {
-    if (CastExpr->getType() == Context.OverloadTy) {
+    if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
       DeclAccessPair Found;
-      FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(CastExpr,
-                                CastTy,
-                                /* Complain */ true,
+      FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(),
+                                DestType,
+                                /*Complain*/ true,
                                 Found);
       
       assert(!Fn && "cast failed but able to resolve overload expression!!");
       (void)Fn;
 
     } else {
-      diagnoseBadCast(*this, msg, (FunctionalStyle ? CT_Functional : CT_CStyle),
-                      R, CastExpr, CastTy);
+      diagnoseBadCast(Self, msg, (FunctionalStyle ? CT_Functional : CT_CStyle),
+                      OpRange, SrcExpr.get(), DestType);
     }
+  } else if (Kind == CK_BitCast) {
+    checkCastAlign();
   }
-  else if (Kind == CK_BitCast)
-    CheckCastAlign(CastExpr, CastTy, R);
 
+  // Clear out SrcExpr if there was a fatal error.
   if (tcr != TC_Success)
+    SrcExpr = ExprError();
+}
+
+ExprResult Sema::CXXBuildCStyleCastExpr(SourceLocation LPLoc,
+                                        TypeSourceInfo *CastTypeInfo,
+                                        SourceLocation RPLoc,
+                                        Expr *CastExpr) {
+  CastOperation Op(*this, CastTypeInfo->getType(), CastExpr);  
+  Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange();
+  Op.OpRange = SourceRange(LPLoc, CastExpr->getLocEnd());
+
+  Op.CheckCStyleCast(/*FunctionalStyle=*/ false);
+  if (Op.SrcExpr.isInvalid())
+    return ExprError();
+
+  return Owned(CStyleCastExpr::Create(Context, Op.ResultType, Op.ValueKind,
+                                      Op.Kind, Op.SrcExpr.take(), &Op.BasePath,
+                                      CastTypeInfo, LPLoc, RPLoc));
+}
+
+ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo,
+                                            SourceLocation LPLoc,
+                                            Expr *CastExpr,
+                                            SourceLocation RPLoc) {
+  CastOperation Op(*this, CastTypeInfo->getType(), CastExpr);
+  Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange();
+  Op.OpRange = SourceRange(Op.DestRange.getBegin(), CastExpr->getLocEnd());
+
+  Op.CheckCStyleCast(/*FunctionalStyle=*/ true);
+  if (Op.SrcExpr.isInvalid())
     return ExprError();
 
-  return Owned(CastExpr);
+  return Owned(CXXFunctionalCastExpr::Create(Context, Op.ResultType,
+                                             Op.ValueKind, CastTypeInfo,
+                                             Op.DestRange.getBegin(),
+                                             Op.Kind, Op.SrcExpr.take(),
+                                             &Op.BasePath, RPLoc));
 }

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=141170&r1=141169&r2=141170&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Wed Oct  5 02:41:44 2011
@@ -495,6 +495,9 @@
     return ExprError();
   }
 
+  // Strip any qualifiers off ValType.
+  ValType = ValType.getUnqualifiedType();
+
   // The majority of builtins return a value, but a few have special return
   // types, so allow them to override appropriately below.
   QualType ResultType = ValType;
@@ -613,11 +616,10 @@
 
     // 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.
-    CastKind Kind = CK_Invalid;
-    ExprValueKind VK = VK_RValue;
-    CXXCastPath BasePath;
-    Arg = CheckCastTypes(Arg.get()->getLocStart(), Arg.get()->getSourceRange(), 
-                         ValType, Arg.take(), Kind, VK, BasePath);
+    // Initialize the argument.
+    InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
+                                                   ValType, /*consume*/ false);
+    Arg = PerformCopyInitialization(Entity, SourceLocation(), Arg);
     if (Arg.isInvalid())
       return ExprError();
 
@@ -627,8 +629,7 @@
     // pass in 42.  The 42 gets converted to char.  This is even more strange
     // for things like 45.123 -> char, etc.
     // FIXME: Do this check.
-    Arg = ImpCastExprToType(Arg.take(), ValType, Kind, VK, &BasePath);
-    TheCall->setArg(i+1, Arg.get());
+    TheCall->setArg(i+1, Arg.take());
   }
 
   ASTContext& Context = this->getASTContext();

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=141170&r1=141169&r2=141170&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Oct  5 02:41:44 2011
@@ -4055,27 +4055,28 @@
   llvm_unreachable("Unhandled scalar cast");
 }
 
-/// CheckCastTypes - Check type constraints for casting between types.
-ExprResult Sema::CheckCastTypes(SourceLocation CastStartLoc,
-                                SourceRange TypeRange, QualType CastType,
-                                Expr *CastExpr, CastKind &Kind,
-                                ExprValueKind &VK, CXXCastPath &BasePath,
-                                bool FunctionalStyle) {
-  if (CastExpr->getType() == Context.UnknownAnyTy)
+/// CheckCastTypes - Check type constraints for casting between types in C.
+ExprResult Sema::CheckCCastTypes(SourceLocation CastStartLoc,
+                                 SourceRange TypeRange, QualType CastType,
+                                 Expr *CastExpr, CastKind &Kind) {
+  assert(!getLangOptions().CPlusPlus);
+
+  if (CastExpr->getType() == Context.UnknownAnyTy) {
+    // We can safely ignore these here because C never has base paths
+    // or casts to l-values.
+    CXXCastPath BasePath;
+    ExprValueKind VK = VK_RValue;
     return checkUnknownAnyCast(TypeRange, CastType, CastExpr, Kind, VK,
                                BasePath);
+  }
 
-  if (getLangOptions().CPlusPlus)
-    return CXXCheckCStyleCast(SourceRange(CastStartLoc,
-                                          CastExpr->getLocEnd()), 
-                              CastType, VK, CastExpr, Kind, BasePath,
-                              FunctionalStyle);
+  ExprResult Result = CheckPlaceholderExpr(CastExpr);
+  if (Result.isInvalid())
+    return ExprError();
+  CastExpr = Result.take();
 
   assert(!CastExpr->getType()->isPlaceholderType());
 
-  // We only support r-value casts in C.
-  VK = VK_RValue;
-
   // C99 6.5.4p2: the cast type needs to be void or scalar and the expression
   // type needs to be scalar.
   if (CastType->isVoidType()) {
@@ -4202,9 +4203,9 @@
     }
   }
 
+  // ARC imposes extra restrictions on casts.
   if (getLangOptions().ObjCAutoRefCount) {
-    // Diagnose problems with Objective-C casts involving lifetime qualifiers.
-    CheckObjCARCConversion(SourceRange(CastStartLoc, CastExpr->getLocEnd()), 
+    CheckObjCARCConversion(SourceRange(CastStartLoc, CastExpr->getLocEnd()),
                            CastType, CastExpr, CCK_CStyleCast);
     
     if (const PointerType *CastPtr = CastType->getAs<PointerType>()) {
@@ -4367,19 +4368,20 @@
 ExprResult
 Sema::BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty,
                           SourceLocation RParenLoc, Expr *CastExpr) {
+  if (getLangOptions().CPlusPlus)
+    return CXXBuildCStyleCastExpr(LParenLoc, Ty, RParenLoc, CastExpr);
+
   CastKind Kind = CK_Invalid;
-  ExprValueKind VK = VK_RValue;
-  CXXCastPath BasePath;
   ExprResult CastResult =
-    CheckCastTypes(LParenLoc, SourceRange(LParenLoc, RParenLoc), Ty->getType(), 
-                   CastExpr, Kind, VK, BasePath);
+    CheckCCastTypes(LParenLoc, SourceRange(LParenLoc, RParenLoc),
+                    Ty->getType(), CastExpr, Kind);
   if (CastResult.isInvalid())
     return ExprError();
   CastExpr = CastResult.take();
 
-  return Owned(CStyleCastExpr::Create(
-    Context, Ty->getType().getNonLValueExprType(Context), VK, Kind, CastExpr,
-    &BasePath, Ty, LParenLoc, RParenLoc));
+  return Owned(CStyleCastExpr::Create(Context, Ty->getType(), VK_RValue, Kind,
+                                      CastExpr, /*base path*/ 0, Ty,
+                                      LParenLoc, RParenLoc));
 }
 
 ExprResult Sema::BuildVectorLiteral(SourceLocation LParenLoc,

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=141170&r1=141169&r2=141170&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Oct  5 02:41:44 2011
@@ -739,27 +739,10 @@
   // If the expression list is a single expression, the type conversion
   // expression is equivalent (in definedness, and if defined in meaning) to the
   // corresponding cast expression.
-  //
   if (NumExprs == 1) {
-    CastKind Kind = CK_Invalid;
-    ExprValueKind VK = VK_RValue;
-    CXXCastPath BasePath;
-    ExprResult CastExpr =
-      CheckCastTypes(TInfo->getTypeLoc().getBeginLoc(),
-                     TInfo->getTypeLoc().getSourceRange(), Ty, Exprs[0],
-                     Kind, VK, BasePath,
-                     /*FunctionalStyle=*/true);
-    if (CastExpr.isInvalid())
-      return ExprError();
-    Exprs[0] = CastExpr.take();
-
+    Expr *Arg = Exprs[0];
     exprs.release();
-
-    return Owned(CXXFunctionalCastExpr::Create(Context,
-                                               Ty.getNonLValueExprType(Context),
-                                               VK, TInfo, TyBeginLoc, Kind,
-                                               Exprs[0], &BasePath,
-                                               RParenLoc));
+    return BuildCXXFunctionalCastExpr(TInfo, LParenLoc, Arg, RParenLoc);
   }
 
   InitializedEntity Entity = InitializedEntity::InitializeTemporary(TInfo);





More information about the cfe-commits mailing list