[cfe-commits] r88733 - in /cfe/trunk: include/clang/AST/DeclCXX.h lib/AST/DeclCXX.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaStmt.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaTemplate/constructor-template.cpp test/SemaTemplate/operator-template.cpp
Douglas Gregor
dgregor at apple.com
Fri Nov 13 17:20:54 PST 2009
Author: dgregor
Date: Fri Nov 13 19:20:54 2009
New Revision: 88733
URL: http://llvm.org/viewvc/llvm-project?rev=88733&view=rev
Log:
If we attempt to add a constructor template specialization that looks
like a copy constructor to the overload set, just ignore it. This
ensures that we don't try to use such a constructor as a copy
constructor *without* triggering diagnostics at the point of
declaration.
Note that we *do* diagnose such copy constructors when explicitly
written by the user (e.g., as an explicit specialization).
Modified:
cfe/trunk/include/clang/AST/DeclCXX.h
cfe/trunk/lib/AST/DeclCXX.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/lib/Sema/SemaStmt.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/test/SemaTemplate/constructor-template.cpp
cfe/trunk/test/SemaTemplate/operator-template.cpp
Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=88733&r1=88732&r2=88733&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Fri Nov 13 19:20:54 2009
@@ -1247,6 +1247,11 @@
/// used for user-defined conversions.
bool isConvertingConstructor(bool AllowExplicit) const;
+ /// \brief Determine whether this is a member template specialization that
+ /// looks like a copy constructor. Such constructors are never used to copy
+ /// an object.
+ bool isCopyConstructorLikeSpecialization() const;
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() == CXXConstructor;
Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=88733&r1=88732&r2=88733&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Fri Nov 13 19:20:54 2009
@@ -752,6 +752,33 @@
(getNumParams() > 1 && getParamDecl(1)->hasDefaultArg());
}
+bool CXXConstructorDecl::isCopyConstructorLikeSpecialization() const {
+ if ((getNumParams() < 1) ||
+ (getNumParams() > 1 && !getParamDecl(1)->hasDefaultArg()) ||
+ (getPrimaryTemplate() == 0) ||
+ (getDescribedFunctionTemplate() != 0))
+ return false;
+
+ const ParmVarDecl *Param = getParamDecl(0);
+
+ ASTContext &Context = getASTContext();
+ CanQualType ParamType = Context.getCanonicalType(Param->getType());
+
+ // Strip off the lvalue reference, if any.
+ if (CanQual<LValueReferenceType> ParamRefType
+ = ParamType->getAs<LValueReferenceType>())
+ ParamType = ParamRefType->getPointeeType();
+
+
+ // Is it the same as our our class type?
+ CanQualType ClassTy
+ = Context.getCanonicalType(Context.getTagDeclType(getParent()));
+ if (ParamType.getUnqualifiedType() != ClassTy)
+ return false;
+
+ return true;
+}
+
CXXDestructorDecl *
CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation L, DeclarationName N,
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=88733&r1=88732&r2=88733&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Nov 13 19:20:54 2009
@@ -2362,13 +2362,18 @@
if (!Constructor->isInvalidDecl() &&
((Constructor->getNumParams() == 1) ||
(Constructor->getNumParams() > 1 &&
- Constructor->getParamDecl(1)->hasDefaultArg()))) {
+ Constructor->getParamDecl(1)->hasDefaultArg())) &&
+ Constructor->getTemplateSpecializationKind()
+ != TSK_ImplicitInstantiation) {
QualType ParamType = Constructor->getParamDecl(0)->getType();
QualType ClassTy = Context.getTagDeclType(ClassDecl);
if (Context.getCanonicalType(ParamType).getUnqualifiedType() == ClassTy) {
SourceLocation ParamLoc = Constructor->getParamDecl(0)->getLocation();
Diag(ParamLoc, diag::err_constructor_byvalue_arg)
<< CodeModificationHint::CreateInsertion(ParamLoc, " const &");
+
+ // FIXME: Rather that making the constructor invalid, we should endeavor
+ // to fix the type.
Constructor->setInvalidDecl();
}
}
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=88733&r1=88732&r2=88733&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Fri Nov 13 19:20:54 2009
@@ -1422,7 +1422,7 @@
= cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl());
else
Constructor = cast<CXXConstructorDecl>(*Con);
-
+
if (!Constructor->isInvalidDecl() &&
Constructor->isConvertingConstructor(AllowExplicit)) {
if (ConstructorTmpl)
@@ -2239,7 +2239,18 @@
if (!CandidateSet.isNewCandidate(Function))
return;
-
+
+ if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Function)){
+ // C++ [class.copy]p3:
+ // A member function template is never instantiated to perform the copy
+ // of a class object to an object of its class type.
+ QualType ClassType = Context.getTypeDeclType(Constructor->getParent());
+ if (NumArgs == 1 &&
+ Constructor->isCopyConstructorLikeSpecialization() &&
+ Context.hasSameUnqualifiedType(ClassType, Args[0]->getType()))
+ return;
+ }
+
// Add this candidate
CandidateSet.push_back(OverloadCandidate());
OverloadCandidate& Candidate = CandidateSet.back();
Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=88733&r1=88732&r2=88733&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Fri Nov 13 19:20:54 2009
@@ -965,9 +965,12 @@
// In C++ the return statement is handled via a copy initialization.
// the C version of which boils down to CheckSingleAssignmentConstraints.
// FIXME: Leaks RetValExp on error.
- if (PerformCopyInitialization(RetValExp, FnRetType, "returning", Elidable))
+ if (PerformCopyInitialization(RetValExp, FnRetType, "returning", Elidable)){
+ // We should still clean up our temporaries, even when we're failing!
+ RetValExp = MaybeCreateCXXExprWithTemporaries(RetValExp, true);
return StmtError();
-
+ }
+
if (RetValExp) CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
}
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=88733&r1=88732&r2=88733&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Fri Nov 13 19:20:54 2009
@@ -658,6 +658,12 @@
TemplateParams, Function);
Function->setDescribedFunctionTemplate(FunctionTemplate);
FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext());
+ } else if (FunctionTemplate) {
+ // Record this function template specialization.
+ Function->setFunctionTemplateSpecialization(SemaRef.Context,
+ FunctionTemplate,
+ &TemplateArgs.getInnermost(),
+ InsertPos);
}
if (InitFunctionInstantiation(Function, D))
@@ -709,14 +715,6 @@
Function->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation);
}
- if (FunctionTemplate && !TemplateParams) {
- // Record this function template specialization.
- Function->setFunctionTemplateSpecialization(SemaRef.Context,
- FunctionTemplate,
- &TemplateArgs.getInnermost(),
- InsertPos);
- }
-
return Function;
}
@@ -811,9 +809,17 @@
if (D->isOutOfLine())
FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext());
Method->setDescribedFunctionTemplate(FunctionTemplate);
- } else if (!FunctionTemplate)
+ } else if (FunctionTemplate) {
+ // Record this function template specialization.
+ Method->setFunctionTemplateSpecialization(SemaRef.Context,
+ FunctionTemplate,
+ &TemplateArgs.getInnermost(),
+ InsertPos);
+ } else {
+ // Record that this is an instantiation of a member function.
Method->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation);
-
+ }
+
// If we are instantiating a member function defined
// out-of-line, the instantiation will have the same lexical
// context (which will be a namespace scope) as the template.
@@ -843,13 +849,6 @@
PrevDecl = 0;
}
- if (FunctionTemplate && !TemplateParams)
- // Record this function template specialization.
- Method->setFunctionTemplateSpecialization(SemaRef.Context,
- FunctionTemplate,
- &TemplateArgs.getInnermost(),
- InsertPos);
-
bool Redeclaration = false;
bool OverloadableAttrRequired = false;
SemaRef.CheckFunctionDeclaration(Method, PrevDecl, false, Redeclaration,
Modified: cfe/trunk/test/SemaTemplate/constructor-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/constructor-template.cpp?rev=88733&r1=88732&r2=88733&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/constructor-template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/constructor-template.cpp Fri Nov 13 19:20:54 2009
@@ -1,5 +1,4 @@
// RUN: clang-cc -fsyntax-only -verify %s
-
struct X0 { // expected-note{{candidate}}
X0(int); // expected-note{{candidate}}
template<typename T> X0(T);
@@ -52,3 +51,34 @@
template <> struct A<int>{A(const A<int>&);};
struct B { A<int> x; B(B& a) : x(a.x) {} };
+struct X2 {
+ X2();
+ X2(X2&);
+ template<typename T> X2(T);
+};
+
+X2 test(bool Cond, X2 x2) {
+ if (Cond)
+ return x2; // okay, uses copy constructor
+
+ return X2(); // expected-error{{incompatible type}}
+}
+
+struct X3 {
+ template<typename T> X3(T);
+};
+
+template<> X3::X3(X3); // expected-error{{must pass its first argument by reference}}
+
+struct X4 {
+ X4();
+ ~X4();
+ X4(X4&);
+ template<typename T> X4(const T&, int = 17);
+};
+
+X4 test_X4(bool Cond, X4 x4) {
+ X4 a(x4, 17); // okay, constructor template
+ X4 b(x4); // okay, copy constructor
+ return X4(); // expected-error{{incompatible type}}
+}
Modified: cfe/trunk/test/SemaTemplate/operator-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/operator-template.cpp?rev=88733&r1=88732&r2=88733&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/operator-template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/operator-template.cpp Fri Nov 13 19:20:54 2009
@@ -11,6 +11,6 @@
template<class X>struct B{typedef X Y;};
template<class X>bool operator==(B<X>*,typename B<X>::Y); // \
expected-error{{overloaded 'operator==' must have at least one parameter of class or enumeration type}} \
-expected-note{{in instantiation of member function}}
+expected-note{{in instantiation of function template specialization}}
int a(B<int> x) { return operator==(&x,1); }
More information about the cfe-commits
mailing list