[cfe-commits] r79919 - in /cfe/trunk: include/clang/AST/DeclCXX.h lib/Sema/Sema.h lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaType.cpp test/SemaTemplate/instantiate-method.cpp
Douglas Gregor
dgregor at apple.com
Mon Aug 24 08:23:48 PDT 2009
Author: dgregor
Date: Mon Aug 24 10:23:48 2009
New Revision: 79919
URL: http://llvm.org/viewvc/llvm-project?rev=79919&view=rev
Log:
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.
Modified:
cfe/trunk/include/clang/AST/DeclCXX.h
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/lib/Sema/SemaType.cpp
cfe/trunk/test/SemaTemplate/instantiate-method.cpp
Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=79919&r1=79918&r2=79919&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Mon Aug 24 10:23:48 2009
@@ -549,9 +549,15 @@
/// getConversions - Retrieve the overload set containing all of the
/// conversion functions in this class.
OverloadedFunctionDecl *getConversionFunctions() {
+ assert((this->isDefinition() ||
+ cast<RecordType>(getTypeForDecl())->isBeingDefined()) &&
+ "getConversionFunctions() called on incomplete type");
return &Conversions;
}
const OverloadedFunctionDecl *getConversionFunctions() const {
+ assert((this->isDefinition() ||
+ cast<RecordType>(getTypeForDecl())->isBeingDefined()) &&
+ "getConversionFunctions() called on incomplete type");
return &Conversions;
}
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=79919&r1=79918&r2=79919&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Aug 24 10:23:48 2009
@@ -2875,12 +2875,13 @@
InstantiateClass(SourceLocation PointOfInstantiation,
CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
const TemplateArgumentList &TemplateArgs,
- bool ExplicitInstantiation);
+ bool ExplicitInstantiation,
+ bool Complain = true);
bool
InstantiateClassTemplateSpecialization(
ClassTemplateSpecializationDecl *ClassTemplateSpec,
- bool ExplicitInstantiation);
+ bool ExplicitInstantiation, bool Complain = true);
void InstantiateClassMembers(SourceLocation PointOfInstantiation,
CXXRecordDecl *Instantiation,
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=79919&r1=79918&r2=79919&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Aug 24 10:23:48 2009
@@ -2847,7 +2847,8 @@
// 92) (this conversion is selected by enumerating the
// applicable conversion functions (13.3.1.6) and choosing
// the best one through overload resolution (13.3)),
- if (!isRValRef && !SuppressUserConversions && T2->isRecordType()) {
+ if (!isRValRef && !SuppressUserConversions && T2->isRecordType() &&
+ !RequireCompleteType(SourceLocation(), T2, 0)) {
// FIXME: Look for conversions in base classes!
CXXRecordDecl *T2RecordDecl
= dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl());
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=79919&r1=79918&r2=79919&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon Aug 24 10:23:48 2009
@@ -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);
-
- // Skip over templated conversion functions; they aren't
- // surrogates.
- if (ConvTemplate)
- continue;
+
+ 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;
- // 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)) {
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=79919&r1=79918&r2=79919&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Mon Aug 24 10:23:48 2009
@@ -624,12 +624,19 @@
/// \param TemplateArgs The template arguments to be substituted into
/// the pattern.
///
+/// \param ExplicitInstantiation whether this is an explicit instantiation
+/// (otherwise, it is an implicit instantiation).
+///
+/// \param Complain whether to complain if the class cannot be instantiated due
+/// to the lack of a definition.
+///
/// \returns true if an error occurred, false otherwise.
bool
Sema::InstantiateClass(SourceLocation PointOfInstantiation,
CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
const TemplateArgumentList &TemplateArgs,
- bool ExplicitInstantiation) {
+ bool ExplicitInstantiation,
+ bool Complain) {
bool Invalid = false;
// Lazily instantiate member templates here.
@@ -639,7 +646,9 @@
CXXRecordDecl *PatternDef
= cast_or_null<CXXRecordDecl>(Pattern->getDefinition(Context));
if (!PatternDef) {
- if (Pattern == Instantiation->getInstantiatedFromMemberClass()) {
+ if (!Complain) {
+ // Say nothing
+ } else if (Pattern == Instantiation->getInstantiatedFromMemberClass()) {
Diag(PointOfInstantiation,
diag::err_implicit_instantiate_member_undefined)
<< Context.getTypeDeclType(Instantiation);
@@ -713,7 +722,8 @@
bool
Sema::InstantiateClassTemplateSpecialization(
ClassTemplateSpecializationDecl *ClassTemplateSpec,
- bool ExplicitInstantiation) {
+ bool ExplicitInstantiation,
+ bool Complain) {
// Perform the actual instantiation on the canonical declaration.
ClassTemplateSpec = cast<ClassTemplateSpecializationDecl>(
ClassTemplateSpec->getCanonicalDecl());
@@ -791,7 +801,8 @@
bool Result = InstantiateClass(ClassTemplateSpec->getLocation(),
ClassTemplateSpec, Pattern, *TemplateArgs,
- ExplicitInstantiation);
+ ExplicitInstantiation,
+ Complain);
for (unsigned I = 0, N = Matched.size(); I != N; ++I) {
// FIXME: Implement TemplateArgumentList::Destroy!
Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=79919&r1=79918&r2=79919&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Mon Aug 24 10:23:48 2009
@@ -1752,7 +1752,8 @@
///
/// @param diag The diagnostic value (e.g.,
/// @c diag::err_typecheck_decl_incomplete_type) that will be used
-/// for the error message if @p T is incomplete.
+/// for the error message if @p T is incomplete. If 0, no diagnostic will be
+/// emitted.
///
/// @param Range1 An optional range in the source code that will be a
/// part of the "incomplete type" error message.
@@ -1792,7 +1793,8 @@
if (Loc.isValid())
ClassTemplateSpec->setLocation(Loc);
return InstantiateClassTemplateSpecialization(ClassTemplateSpec,
- /*ExplicitInstantiation=*/false);
+ /*ExplicitInstantiation=*/false,
+ /*Complain=*/diag != 0);
}
} else if (CXXRecordDecl *Rec
= dyn_cast<CXXRecordDecl>(Record->getDecl())) {
@@ -1805,11 +1807,15 @@
Spec = dyn_cast<ClassTemplateSpecializationDecl>(Parent);
assert(Spec && "Not a member of a class template specialization?");
return InstantiateClass(Loc, Rec, Pattern, Spec->getTemplateArgs(),
- /*ExplicitInstantiation=*/false);
+ /*ExplicitInstantiation=*/false,
+ /*Complain=*/diag != 0);
}
}
}
+ if (diag == 0)
+ return true;
+
if (PrintType.isNull())
PrintType = T;
Modified: cfe/trunk/test/SemaTemplate/instantiate-method.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-method.cpp?rev=79919&r1=79918&r2=79919&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-method.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-method.cpp Mon Aug 24 10:23:48 2009
@@ -72,3 +72,12 @@
int i = ci;
int *ip = cip;
}
+
+// PR4660
+template<class T> struct A0 { operator T*(); };
+template<class T> struct A1;
+
+int *a(A0<int> &x0, A1<int> &x1) {
+ int *y0 = x0;
+ int *y1 = x1; // expected-error{{initializing}}
+}
More information about the cfe-commits
mailing list