diff options
-rw-r--r-- | lib/Sema/Sema.h | 10 | ||||
-rw-r--r-- | lib/Sema/SemaCXXCast.cpp | 112 | ||||
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 107 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 21 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 13 | ||||
-rw-r--r-- | lib/Sema/SemaInit.cpp | 8 | ||||
-rw-r--r-- | lib/Sema/SemaInit.h | 4 | ||||
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 6 | ||||
-rw-r--r-- | test/SemaTemplate/instantiate-expr-2.cpp | 19 |
10 files changed, 70 insertions, 234 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index db8f34d1d1..33aceba774 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -2161,12 +2161,6 @@ public: /// 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 @@ public: /// 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 @@ public: /// 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. diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp index 716e51b7dd..a6e5570752 100644 --- a/lib/Sema/SemaCXXCast.cpp +++ b/lib/Sema/SemaCXXCast.cpp @@ -46,8 +46,7 @@ static void CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType, 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 @@ static TryCastResult TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, 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 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, } 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 @@ CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType, /// 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 @@ CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType, 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 @@ CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType, 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 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr, // 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 @@ TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType, 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 @@ TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType, 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 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, } 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 @@ bool Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr, 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, diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 64e0e264af..033a36c90e 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -409,9 +409,7 @@ bool Sema::SemaBuiltinAtomicOverloaded(CallExpr *TheCall) { // 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 diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 8318b316d8..4ce428465a 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -4271,113 +4271,6 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, 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. diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index d42129c489..9b2ec58804 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -3789,11 +3789,9 @@ static CastExpr::CastKind getScalarCastKind(ASTContext &Context, /// 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 @@ Sema::BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, 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)); diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index c906d22d6f..f52bc84467 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -504,21 +504,10 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep, // 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, diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index edff4a5396..e50a860265 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -2036,6 +2036,10 @@ bool InitializationSequence::isAmbiguous() const { 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 @@ InitializationSequence::Perform(Sema &S, } case SK_ConstructorInitialization: { + unsigned NumArgs = Args.size(); CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Step->Function.Function); @@ -3523,8 +3528,9 @@ InitializationSequence::Perform(Sema &S, 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). diff --git a/lib/Sema/SemaInit.h b/lib/Sema/SemaInit.h index 7c6327f8c7..65ee42042c 100644 --- a/lib/Sema/SemaInit.h +++ b/lib/Sema/SemaInit.h @@ -606,6 +606,10 @@ public: /// \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. /// diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 0c55cf5c5c..74c64d3881 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -126,8 +126,12 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { 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(); diff --git a/test/SemaTemplate/instantiate-expr-2.cpp b/test/SemaTemplate/instantiate-expr-2.cpp index 4da4e713ec..b91b398a80 100644 --- a/test/SemaTemplate/instantiate-expr-2.cpp +++ b/test/SemaTemplate/instantiate-expr-2.cpp @@ -193,3 +193,22 @@ namespace N12 { 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); + +} |