aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaOverload.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2008-10-29 00:13:59 +0000
committerDouglas Gregor <dgregor@apple.com>2008-10-29 00:13:59 +0000
commit27c8dc06f65d7abcf6a7e7f64a7960c9a150ca01 (patch)
tree11c0cafe9243e679b669258afcbf41260033c7be /lib/Sema/SemaOverload.cpp
parent1b450b092a053896e96f0355cf7c7cdc9bba9eab (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.cpp115
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