diff options
author | Douglas Gregor <dgregor@apple.com> | 2008-10-29 00:13:59 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2008-10-29 00:13:59 +0000 |
commit | 27c8dc06f65d7abcf6a7e7f64a7960c9a150ca01 (patch) | |
tree | 11c0cafe9243e679b669258afcbf41260033c7be /lib/Sema/SemaOverload.cpp | |
parent | 1b450b092a053896e96f0355cf7c7cdc9bba9eab (diff) |
Implement initialization of a reference (C++ [dcl.init.ref]) as part
of copy initialization. Other pieces of the puzzle:
- Try/Perform-ImplicitConversion now handles implicit conversions
that don't involve references.
- Try/Perform-CopyInitialization uses
CheckSingleAssignmentConstraints for C. PerformCopyInitialization
is now used for all argument passing and returning values from a
function.
- Diagnose errors with declaring references and const values without
an initializer. (Uses a new Action callback, ActOnUninitializedDecl).
We do not yet have implicit conversion sequences for reference
binding, which means that we don't have any overloading support for
reference parameters yet.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58353 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaOverload.cpp')
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 115 |
1 files changed, 82 insertions, 33 deletions
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 7c78365686..8e765485b1 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -312,11 +312,10 @@ Sema::IsOverload(FunctionDecl *New, Decl* OldD, } } -/// TryCopyInitialization - Attempt to copy-initialize a value of the -/// given type (ToType) from the given expression (Expr), as one would -/// do when copy-initializing a function parameter. This function -/// returns an implicit conversion sequence that can be used to -/// perform the initialization. Given +/// TryImplicitConversion - Attempt to perform an implicit conversion +/// from the given expression (Expr) to the given type (ToType). This +/// function returns an implicit conversion sequence that can be used +/// to perform the initialization. Given /// /// void f(float f); /// void g(int i) { f(i); } @@ -332,7 +331,7 @@ Sema::IsOverload(FunctionDecl *New, Decl* OldD, /// but will instead return an implicit conversion sequence of kind /// "BadConversion". ImplicitConversionSequence -Sema::TryCopyInitialization(Expr* From, QualType ToType) +Sema::TryImplicitConversion(Expr* From, QualType ToType) { ImplicitConversionSequence ICS; @@ -343,32 +342,6 @@ Sema::TryCopyInitialization(Expr* From, QualType ToType) ICS.Standard.Deprecated = false; ICS.Standard.FromTypePtr = FromType.getAsOpaquePtr(); - if (const ReferenceType *ToTypeRef = ToType->getAsReferenceType()) { - // FIXME: This is a hack to deal with the initialization of - // references the way that the C-centric code elsewhere deals with - // references, by only allowing them if the referred-to type is - // exactly the same. This means that we're only handling the - // direct-binding case. The code will be replaced by an - // implementation of C++ 13.3.3.1.4 once we have the - // initialization of references implemented. - QualType ToPointee = Context.getCanonicalType(ToTypeRef->getPointeeType()); - - // Get down to the canonical type that we're converting from. - if (const ReferenceType *FromTypeRef = FromType->getAsReferenceType()) - FromType = FromTypeRef->getPointeeType(); - FromType = Context.getCanonicalType(FromType); - - ICS.Standard.First = ICK_Identity; - ICS.Standard.Second = ICK_Identity; - ICS.Standard.Third = ICK_Identity; - ICS.Standard.ToTypePtr = ToType.getAsOpaquePtr(); - - if (FromType != ToPointee) - ICS.ConversionKind = ImplicitConversionSequence::BadConversion; - - return ICS; - } - // The first conversion can be an lvalue-to-rvalue conversion, // array-to-pointer conversion, or function-to-pointer conversion // (C++ 4p1). @@ -482,18 +455,37 @@ Sema::TryCopyInitialization(Expr* From, QualType ToType) ICS.Standard.Second = ICK_Identity; } + QualType CanonFrom; + QualType CanonTo; // The third conversion can be a qualification conversion (C++ 4p1). if (IsQualificationConversion(FromType, ToType)) { ICS.Standard.Third = ICK_Qualification; FromType = ToType; + CanonFrom = Context.getCanonicalType(FromType); + CanonTo = Context.getCanonicalType(ToType); } else { // No conversion required ICS.Standard.Third = ICK_Identity; + + // C++ [dcl.init]p14 last bullet: + // Note: an expression of type "cv1 T" can initialize an object + // of type “cv2 T” independently of the cv-qualifiers cv1 and + // cv2. -- end note] + // + // FIXME: Where is the normative text? + CanonFrom = Context.getCanonicalType(FromType); + CanonTo = Context.getCanonicalType(ToType); + if (!FromType->isRecordType() && + CanonFrom.getUnqualifiedType() == CanonTo.getUnqualifiedType() && + CanonFrom.getCVRQualifiers() != CanonTo.getCVRQualifiers()) { + FromType = ToType; + CanonFrom = CanonTo; + } } // If we have not converted the argument type to the parameter type, // this is a bad conversion sequence. - if (Context.getCanonicalType(FromType) != Context.getCanonicalType(ToType)) + if (CanonFrom != CanonTo) ICS.ConversionKind = ImplicitConversionSequence::BadConversion; ICS.Standard.ToTypePtr = FromType.getAsOpaquePtr(); @@ -1054,6 +1046,63 @@ Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1, return ImplicitConversionSequence::Indistinguishable; } +/// TryCopyInitialization - Try to copy-initialize a value of type +/// ToType from the expression From. Return the implicit conversion +/// sequence required to pass this argument, which may be a bad +/// conversion sequence (meaning that the argument cannot be passed to +/// a parameter of this type). This is user for argument passing, +ImplicitConversionSequence +Sema::TryCopyInitialization(Expr *From, QualType ToType) { + if (!getLangOptions().CPlusPlus) { + // In C, argument passing is the same as performing an assignment. + AssignConvertType ConvTy = + CheckSingleAssignmentConstraints(ToType, From); + ImplicitConversionSequence ICS; + if (getLangOptions().NoExtensions? ConvTy != Compatible + : ConvTy == Incompatible) + ICS.ConversionKind = ImplicitConversionSequence::BadConversion; + else + ICS.ConversionKind = ImplicitConversionSequence::StandardConversion; + return ICS; + } else if (ToType->isReferenceType()) { + ImplicitConversionSequence ICS; + if (CheckReferenceInit(From, ToType, /*Complain=*/false)) + ICS.ConversionKind = ImplicitConversionSequence::BadConversion; + else + ICS.ConversionKind = ImplicitConversionSequence::StandardConversion; + return ICS; + } else { + return TryImplicitConversion(From, ToType); + } +} + +/// PerformArgumentPassing - Pass the argument Arg into a parameter of +/// type ToType. Returns true (and emits a diagnostic) if there was +/// an error, returns false if the initialization succeeded. +bool Sema::PerformCopyInitialization(Expr *&From, QualType ToType, + const char* Flavor) { + if (!getLangOptions().CPlusPlus) { + // In C, argument passing is the same as performing an assignment. + QualType FromType = From->getType(); + AssignConvertType ConvTy = + CheckSingleAssignmentConstraints(ToType, From); + + return DiagnoseAssignmentResult(ConvTy, From->getLocStart(), ToType, + FromType, From, Flavor); + } else if (ToType->isReferenceType()) { + return CheckReferenceInit(From, ToType); + } else { + if (PerformImplicitConversion(From, ToType)) + return Diag(From->getSourceRange().getBegin(), + diag::err_typecheck_convert_incompatible, + ToType.getAsString(), From->getType().getAsString(), + Flavor, + From->getSourceRange()); + else + return false; + } +} + /// AddOverloadCandidate - Adds the given function to the set of /// candidate functions, using the given function call arguments. void |