Try to complete a type before looking for conversion functions within
that type. Note that we do not produce a diagnostic if the type is
incomplete; rather, we just don't look for conversion functions. Fixes PR4660.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@79919 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 0a65a36..152d4ad 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -1392,6 +1392,9 @@
if (!AllowConversionFunctions) {
// Don't allow any conversion functions to enter the overload set.
+ } else if (RequireCompleteType(From->getLocStart(), From->getType(), 0,
+ From->getSourceRange())) {
+ // No conversion functions from incomplete types.
} else if (const RecordType *FromRecordType
= From->getType()->getAs<RecordType>()) {
if (CXXRecordDecl *FromRecordDecl
@@ -2699,6 +2702,10 @@
/// used in the built-in candidates.
TypeSet EnumerationTypes;
+ /// Sema - The semantic analysis instance where we are building the
+ /// candidate type set.
+ Sema &SemaRef;
+
/// Context - The AST context in which we will build the type sets.
ASTContext &Context;
@@ -2709,7 +2716,8 @@
/// iterator - Iterates through the types that are part of the set.
typedef TypeSet::iterator iterator;
- BuiltinCandidateTypeSet(ASTContext &Context) : Context(Context) { }
+ BuiltinCandidateTypeSet(Sema &SemaRef)
+ : SemaRef(SemaRef), Context(SemaRef.Context) { }
void AddTypesConvertedFrom(QualType Ty, bool AllowUserConversions,
bool AllowExplicitConversions);
@@ -2860,6 +2868,11 @@
EnumerationTypes.insert(Ty);
} else if (AllowUserConversions) {
if (const RecordType *TyRec = Ty->getAs<RecordType>()) {
+ if (SemaRef.RequireCompleteType(SourceLocation(), Ty, 0)) {
+ // No conversion functions in incomplete types.
+ return;
+ }
+
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl());
// FIXME: Visit conversion functions in the base classes, too.
OverloadedFunctionDecl *Conversions
@@ -2942,7 +2955,7 @@
// Find all of the types that the arguments can convert to, but only
// if the operator we're looking at has built-in operator candidates
// that make use of these types.
- BuiltinCandidateTypeSet CandidateTypes(Context);
+ BuiltinCandidateTypeSet CandidateTypes(*this);
if (Op == OO_Less || Op == OO_Greater || Op == OO_LessEqual ||
Op == OO_GreaterEqual || Op == OO_EqualEqual || Op == OO_ExclaimEqual ||
Op == OO_Plus || (Op == OO_Minus && NumArgs == 2) || Op == OO_Equal ||
@@ -4612,33 +4625,35 @@
// functions for each conversion function declared in an
// accessible base class provided the function is not hidden
// within T by another intervening declaration.
- //
- // FIXME: Look in base classes for more conversion operators!
- OverloadedFunctionDecl *Conversions
- = cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions();
- for (OverloadedFunctionDecl::function_iterator
- Func = Conversions->function_begin(),
- FuncEnd = Conversions->function_end();
- Func != FuncEnd; ++Func) {
- CXXConversionDecl *Conv;
- FunctionTemplateDecl *ConvTemplate;
- GetFunctionAndTemplate(*Func, Conv, ConvTemplate);
+
+ if (!RequireCompleteType(SourceLocation(), Object->getType(), 0)) {
+ // FIXME: Look in base classes for more conversion operators!
+ OverloadedFunctionDecl *Conversions
+ = cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions();
+ for (OverloadedFunctionDecl::function_iterator
+ Func = Conversions->function_begin(),
+ FuncEnd = Conversions->function_end();
+ Func != FuncEnd; ++Func) {
+ CXXConversionDecl *Conv;
+ FunctionTemplateDecl *ConvTemplate;
+ GetFunctionAndTemplate(*Func, Conv, ConvTemplate);
- // Skip over templated conversion functions; they aren't
- // surrogates.
- if (ConvTemplate)
- continue;
+ // Skip over templated conversion functions; they aren't
+ // surrogates.
+ if (ConvTemplate)
+ continue;
- // Strip the reference type (if any) and then the pointer type (if
- // any) to get down to what might be a function type.
- QualType ConvType = Conv->getConversionType().getNonReferenceType();
- if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
- ConvType = ConvPtrType->getPointeeType();
+ // Strip the reference type (if any) and then the pointer type (if
+ // any) to get down to what might be a function type.
+ QualType ConvType = Conv->getConversionType().getNonReferenceType();
+ if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
+ ConvType = ConvPtrType->getPointeeType();
- if (const FunctionProtoType *Proto = ConvType->getAsFunctionProtoType())
- AddSurrogateCandidate(Conv, Proto, Object, Args, NumArgs, CandidateSet);
+ if (const FunctionProtoType *Proto = ConvType->getAsFunctionProtoType())
+ AddSurrogateCandidate(Conv, Proto, Object, Args, NumArgs, CandidateSet);
+ }
}
-
+
// Perform overload resolution.
OverloadCandidateSet::iterator Best;
switch (BestViableFunction(CandidateSet, Object->getLocStart(), Best)) {