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. llvm-svn: 101549
This commit is contained in:
parent
d43a12df56
commit
b33eed0ced
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue