[cfe-commits] r61048 - in /cfe/trunk: include/clang/AST/DeclCXX.h include/clang/Basic/DiagnosticKinds.def lib/AST/DeclCXX.cpp lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaOverload.cpp test/SemaCXX/constructor.cpp test/SemaCXX/overload-decl.cpp
Douglas Gregor
dgregor at apple.com
Mon Dec 15 13:24:18 PST 2008
Author: dgregor
Date: Mon Dec 15 15:24:18 2008
New Revision: 61048
URL: http://llvm.org/viewvc/llvm-project?rev=61048&view=rev
Log:
Place constructors and destructors into the DeclContext of the class,
just like all other members, and remove the special variables in
CXXRecordDecl to store them. This eliminates a lot of special-case
code for constructors and destructors, including
ActOnConstructor/ActOnDeclarator and special lookup rules in
LookupDecl. The result is far more uniform and manageable.
Diagnose the redeclaration of member functions.
Modified:
cfe/trunk/include/clang/AST/DeclCXX.h
cfe/trunk/include/clang/Basic/DiagnosticKinds.def
cfe/trunk/lib/AST/DeclCXX.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/test/SemaCXX/constructor.cpp
cfe/trunk/test/SemaCXX/overload-decl.cpp
Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=61048&r1=61047&r2=61048&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Mon Dec 15 15:24:18 2008
@@ -260,9 +260,13 @@
bool UserDeclaredConstructor : 1;
/// UserDeclaredCopyConstructor - True when this class has a
- /// user-defined copy constructor.
+ /// user-declared copy constructor.
bool UserDeclaredCopyConstructor : 1;
+ /// UserDeclaredDestructor - True when this class has a
+ /// user-declared destructor.
+ bool UserDeclaredDestructor : 1;
+
/// Aggregate - True when this class is an aggregate.
bool Aggregate : 1;
@@ -277,14 +281,6 @@
/// NumBases - The number of base class specifiers in Bases.
unsigned NumBases;
- /// Constructors - Overload set containing the constructors of this
- /// C++ class. Each of the entries in this overload set is a
- /// CXXConstructorDecl.
- OverloadedFunctionDecl Constructors;
-
- // Destructor - The destructor of this C++ class.
- CXXDestructorDecl *Destructor;
-
/// Conversions - Overload set containing the conversion functions
/// of this C++ class (but not its inherited conversion
/// functions). Each of the entries in this overload set is a
@@ -321,20 +317,14 @@
base_class_iterator bases_end() { return Bases + NumBases; }
base_class_const_iterator bases_end() const { return Bases + NumBases; }
- /// getConstructors - Retrieve the overload set containing all of
- /// the constructors of this class.
- OverloadedFunctionDecl *getConstructors() { return &Constructors; }
-
- /// getConstructors - Retrieve the overload set containing all of
- /// the constructors of this class.
- const OverloadedFunctionDecl *getConstructors() const { return &Constructors; }
-
/// hasConstCopyConstructor - Determines whether this class has a
/// copy constructor that accepts a const-qualified argument.
bool hasConstCopyConstructor(ASTContext &Context) const;
- /// addConstructor - Add another constructor to the list of constructors.
- void addConstructor(ASTContext &Context, CXXConstructorDecl *ConDecl);
+ /// addedConstructor - Notify the class that another constructor has
+ /// been added. This routine helps maintain information about the
+ /// class based on which constructors have been added.
+ void addedConstructor(ASTContext &Context, CXXConstructorDecl *ConDecl);
/// hasUserDeclaredConstructor - Whether this class has any
/// user-declared constructors. When true, a default constructor
@@ -348,13 +338,16 @@
return UserDeclaredCopyConstructor;
}
- /// getDestructor - Retrieve the destructor for this class.
- CXXDestructorDecl *getDestructor() const { return Destructor; }
-
- /// setDestructor - Set the destructor for this class.
- void setDestructor(CXXDestructorDecl *Destructor) {
- assert(!this->Destructor && "Already have a destructor!");
- this->Destructor = Destructor;
+ /// hasUserDeclaredDestructor - Whether this class has a
+ /// user-declared destructor. When false, a destructor will be
+ /// implicitly declared.
+ bool hasUserDeclaredDestructor() const { return UserDeclaredDestructor; }
+
+ /// setUserDeclaredDestructor - Set whether this class has a
+ /// user-declared destructor. If not set by the time the class is
+ /// fully defined, a destructor will be implicitly declared.
+ void setUserDeclaredDestructor(bool UCD = true) {
+ UserDeclaredDestructor = UCD;
}
/// getConversions - Retrieve the overload set containing all of the
@@ -402,8 +395,6 @@
return static_cast<CXXRecordDecl *>(const_cast<DeclContext*>(DC));
}
- virtual void Destroy(ASTContext& C);
-
protected:
/// EmitImpl - Serialize this CXXRecordDecl. Called by Decl::Emit.
// FIXME: Implement this.
Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=61048&r1=61047&r2=61048&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Mon Dec 15 15:24:18 2008
@@ -1169,6 +1169,7 @@
"incomplete definition of type %0")
DIAG(err_typecheck_no_member, ERROR,
"no member named %0")
+DIAG(err_member_redeclared, ERROR, "class member cannot be redeclared")
DIAG(err_typecheck_ivar_variable_size, ERROR,
"instance variables must have a constant size")
// FIXME: Improve with %select
Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=61048&r1=61047&r2=61048&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Mon Dec 15 15:24:18 2008
@@ -40,9 +40,8 @@
SourceLocation L, IdentifierInfo *Id)
: RecordDecl(CXXRecord, TK, DC, L, Id),
UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
- Aggregate(true), Polymorphic(false), Bases(0), NumBases(0),
- Constructors(DC, DeclarationName()),
- Destructor(0),
+ UserDeclaredDestructor(false), Aggregate(true), Polymorphic(false),
+ Bases(0), NumBases(0),
Conversions(DC, DeclarationName()) { }
CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
@@ -58,18 +57,6 @@
delete [] Bases;
}
-void CXXRecordDecl::Destroy(ASTContext &C) {
- for (OverloadedFunctionDecl::function_iterator func
- = Constructors.function_begin();
- func != Constructors.function_end(); ++func)
- (*func)->Destroy(C);
-
- if (isDefinition())
- Destructor->Destroy(C);
-
- RecordDecl::Destroy(C);
-}
-
void
CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
unsigned NumBases) {
@@ -88,20 +75,35 @@
}
bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const {
- for (OverloadedFunctionDecl::function_const_iterator Con
- = Constructors.function_begin();
- Con != Constructors.function_end(); ++Con) {
- unsigned TypeQuals;
+ QualType ClassType = Context.getTypeDeclType(const_cast<CXXRecordDecl*>(this));
+ DeclarationName ConstructorName
+ = Context.DeclarationNames.getCXXConstructorName(
+ Context.getCanonicalType(ClassType));
+ unsigned TypeQuals;
+ DeclContext::lookup_const_result Lookup
+ = this->lookup(Context, ConstructorName);
+ if (Lookup.first == Lookup.second)
+ return false;
+ else if (OverloadedFunctionDecl *Constructors
+ = dyn_cast<OverloadedFunctionDecl>(*Lookup.first)) {
+ for (OverloadedFunctionDecl::function_const_iterator Con
+ = Constructors->function_begin();
+ Con != Constructors->function_end(); ++Con) {
if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context, TypeQuals) &&
(TypeQuals & QualType::Const != 0))
return true;
+ }
+ } else if (CXXConstructorDecl *Constructor
+ = dyn_cast<CXXConstructorDecl>(*Lookup.first)) {
+ return Constructor->isCopyConstructor(Context, TypeQuals) &&
+ (TypeQuals & QualType::Const != 0);
}
return false;
}
void
-CXXRecordDecl::addConstructor(ASTContext &Context,
- CXXConstructorDecl *ConDecl) {
+CXXRecordDecl::addedConstructor(ASTContext &Context,
+ CXXConstructorDecl *ConDecl) {
if (!ConDecl->isImplicitlyDeclared()) {
// Note that we have a user-declared constructor.
UserDeclaredConstructor = true;
@@ -116,8 +118,6 @@
if (ConDecl->isCopyConstructor(Context))
UserDeclaredCopyConstructor = true;
}
-
- Constructors.addOverload(ConDecl);
}
void CXXRecordDecl::addConversionFunction(ASTContext &Context,
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=61048&r1=61047&r2=61048&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Dec 15 15:24:18 2008
@@ -963,8 +963,6 @@
FunctionDecl::StorageClass& SC);
bool CheckConversionDeclarator(Declarator &D, QualType &R,
FunctionDecl::StorageClass& SC);
- DeclTy *ActOnConstructorDeclarator(CXXConstructorDecl *Constructor);
- DeclTy *ActOnDestructorDeclarator(CXXDestructorDecl *Destructor);
DeclTy *ActOnConversionDeclarator(CXXConversionDecl *Conversion);
//===--------------------------------------------------------------------===//
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=61048&r1=61047&r2=61048&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Dec 15 15:24:18 2008
@@ -138,20 +138,20 @@
FD->getDeclName());
Ovl->addOverload(cast<FunctionDecl>(Prev));
- // If there is an ame binding for the existing FunctionDecl,
- // remove it.
- for (IdentifierResolver::iterator I
- = IdResolver.begin(FD->getDeclName(), FD->getDeclContext(),
- false/*LookInParentCtx*/),
- E = IdResolver.end(); I != E; ++I) {
- if (*I == Prev) {
- IdResolver.RemoveDecl(*I);
- S->RemoveDecl(*I);
- break;
- }
- }
+ // If there is a name binding for the existing FunctionDecl,
+ // remove it.
+ for (IdentifierResolver::iterator I
+ = IdResolver.begin(FD->getDeclName(), FD->getDeclContext(),
+ false/*LookInParentCtx*/),
+ E = IdResolver.end(); I != E; ++I) {
+ if (*I == Prev) {
+ IdResolver.RemoveDecl(*I);
+ S->RemoveDecl(*I);
+ break;
+ }
+ }
- // Add the name binding for the OverloadedFunctionDecl.
+ // Add the name binding for the OverloadedFunctionDecl.
IdResolver.AddDecl(Ovl);
// Update the context with the newly-created overloaded
@@ -246,24 +246,6 @@
} else if (LookupCtx) {
assert(getLangOptions().CPlusPlus && "No qualified name lookup in C");
- switch (Name.getNameKind()) {
- case DeclarationName::CXXConstructorName:
- if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(LookupCtx))
- return const_cast<CXXRecordDecl *>(Record)->getConstructors();
- else
- return 0;
-
- case DeclarationName::CXXDestructorName:
- if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(LookupCtx))
- return Record->getDestructor();
- else
- return 0;
-
- default:
- // Normal name lookup.
- break;
- }
-
// Perform qualified name lookup into the LookupCtx.
// FIXME: Will need to look into base classes and such.
DeclContext::lookup_const_iterator I, E;
@@ -565,6 +547,26 @@
Diag(Old->getLocation(), PrevDiag);
return New;
}
+
+ // C++ [class.mem]p1:
+ // [...] A member shall not be declared twice in the
+ // member-specification, except that a nested class or member
+ // class template can be declared and then later defined.
+ if (OldMethod->getLexicalDeclContext() ==
+ NewMethod->getLexicalDeclContext()) {
+ unsigned NewDiag;
+ if (isa<CXXConstructorDecl>(OldMethod))
+ NewDiag = diag::err_constructor_redeclared;
+ else if (isa<CXXDestructorDecl>(NewMethod))
+ NewDiag = diag::err_destructor_redeclared;
+ else if (isa<CXXConversionDecl>(NewMethod))
+ NewDiag = diag::err_conv_function_redeclared;
+ else
+ NewDiag = diag::err_member_redeclared;
+
+ Diag(New->getLocation(), NewDiag);
+ Diag(Old->getLocation(), PrevDiag);
+ }
}
// (C++98 8.3.5p3):
@@ -1117,6 +1119,11 @@
// Handle attributes.
ProcessDeclAttributes(NewFD, D);
+ // Set the lexical context. If the declarator has a C++
+ // scope specifier, the lexical context will be different
+ // from the semantic context.
+ NewFD->setLexicalDeclContext(CurContext);
+
// Handle GNU asm-label extension (encoded as an attribute).
if (Expr *E = (Expr*) D.getAsmLabel()) {
// The parser guarantees this is a string.
@@ -1189,18 +1196,33 @@
}
}
- // C++ constructors and destructors are handled by separate
- // routines, since they don't require any declaration merging (C++
- // [class.mfct]p2) and they aren't ever pushed into scope, because
- // they can't be found by name lookup anyway (C++ [class.ctor]p2).
- if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD))
- return ActOnConstructorDeclarator(Constructor);
- else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(NewFD))
- return ActOnDestructorDeclarator(Destructor);
-
- // Extra checking for conversion functions, including recording
- // the conversion function in its class.
- if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(NewFD))
+ if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD)) {
+ CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(DC);
+
+ // C++ [class.copy]p3:
+ // A declaration of a constructor for a class X is ill-formed if
+ // its first parameter is of type (optionally cv-qualified) X and
+ // either there are no other parameters or else all other
+ // parameters have default arguments.
+ if ((Constructor->getNumParams() == 1) ||
+ (Constructor->getNumParams() > 1 &&
+ Constructor->getParamDecl(1)->getDefaultArg() != 0)) {
+ QualType ParamType = Constructor->getParamDecl(0)->getType();
+ QualType ClassTy = Context.getTagDeclType(ClassDecl);
+ if (Context.getCanonicalType(ParamType).getUnqualifiedType()
+ == ClassTy) {
+ Diag(Constructor->getLocation(), diag::err_constructor_byvalue_arg)
+ << SourceRange(Constructor->getParamDecl(0)->getLocation());
+ Constructor->setInvalidDecl();
+ }
+ }
+
+ // Notify the class that we've added a constructor.
+ ClassDecl->addedConstructor(Context, Constructor);
+ }
+ else if (isa<CXXDestructorDecl>(NewFD))
+ cast<CXXRecordDecl>(NewFD->getParent())->setUserDeclaredDestructor(true);
+ else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(NewFD))
ActOnConversionDeclarator(Conversion);
// Extra checking for C++ overloaded operators (C++ [over.oper]).
@@ -1268,11 +1290,6 @@
CheckCXXDefaultArguments(NewFD);
}
- // Set the lexical context. If the declarator has a C++
- // scope specifier, the lexical context will be different
- // from the semantic context.
- NewFD->setLexicalDeclContext(CurContext);
-
return NewFD;
}
}
@@ -1965,7 +1982,9 @@
// function return type, in the declaration of a class member
// within its class declaration (9.2), and where the extern
// specifier is explicitly used.
- if (Type->isReferenceType() && Var->getStorageClass() != VarDecl::Extern) {
+ if (Type->isReferenceType() &&
+ Var->getStorageClass() != VarDecl::Extern &&
+ Var->getStorageClass() != VarDecl::PrivateExtern) {
Diag(Var->getLocation(), diag::err_reference_var_requires_init)
<< Var->getDeclName()
<< SourceRange(Var->getLocation(), Var->getLocation());
@@ -1984,7 +2003,9 @@
QualType InitType = Type;
if (const ArrayType *Array = Context.getAsArrayType(Type))
InitType = Array->getElementType();
- if (InitType->isRecordType()) {
+ if (Var->getStorageClass() != VarDecl::Extern &&
+ Var->getStorageClass() != VarDecl::PrivateExtern &&
+ InitType->isRecordType()) {
const CXXConstructorDecl *Constructor
= PerformInitializationByConstructor(InitType, 0, 0,
Var->getLocation(),
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=61048&r1=61047&r2=61048&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Dec 15 15:24:18 2008
@@ -744,7 +744,10 @@
/*isInline=*/true,
/*isImplicitlyDeclared=*/true);
DefaultCon->setAccess(AS_public);
- ClassDecl->addConstructor(Context, DefaultCon);
+ ClassDecl->addDecl(Context, DefaultCon);
+
+ // Notify the class that we've added a constructor.
+ ClassDecl->addedConstructor(Context, DefaultCon);
}
if (!ClassDecl->hasUserDeclaredCopyConstructor()) {
@@ -820,10 +823,27 @@
ArgType, VarDecl::None, 0, 0);
CopyConstructor->setParams(&FromParam, 1);
- ClassDecl->addConstructor(Context, CopyConstructor);
+ ClassDecl->addedConstructor(Context, CopyConstructor);
+ DeclContext::lookup_result Lookup = ClassDecl->lookup(Context, Name);
+ if (Lookup.first == Lookup.second
+ || (!isa<CXXConstructorDecl>(*Lookup.first) &&
+ !isa<OverloadedFunctionDecl>(*Lookup.first)))
+ ClassDecl->addDecl(Context, CopyConstructor);
+ else {
+ OverloadedFunctionDecl *Ovl
+ = dyn_cast<OverloadedFunctionDecl>(*Lookup.first);
+ if (!Ovl) {
+ Ovl = OverloadedFunctionDecl::Create(Context, ClassDecl, Name);
+ Ovl->addOverload(cast<CXXConstructorDecl>(*Lookup.first));
+ ClassDecl->insert(Context, Ovl);
+ }
+
+ Ovl->addOverload(CopyConstructor);
+ ClassDecl->addDecl(Context, CopyConstructor, false);
+ }
}
- if (!ClassDecl->getDestructor()) {
+ if (!ClassDecl->hasUserDeclaredDestructor()) {
// C++ [class.dtor]p2:
// If a class has no user-declared destructor, a destructor is
// declared implicitly. An implicitly-declared destructor is an
@@ -838,7 +858,7 @@
/*isInline=*/true,
/*isImplicitlyDeclared=*/true);
Destructor->setAccess(AS_public);
- ClassDecl->setDestructor(Destructor);
+ ClassDecl->addDecl(Context, Destructor);
}
// FIXME: Implicit copy assignment operator
@@ -1087,101 +1107,6 @@
return isInvalid;
}
-/// ActOnConstructorDeclarator - Called by ActOnDeclarator to complete
-/// the declaration of the given C++ constructor ConDecl that was
-/// built from declarator D. This routine is responsible for checking
-/// that the newly-created constructor declaration is well-formed and
-/// for recording it in the C++ class. Example:
-///
-/// @code
-/// class X {
-/// X(); // X::X() will be the ConDecl.
-/// };
-/// @endcode
-Sema::DeclTy *Sema::ActOnConstructorDeclarator(CXXConstructorDecl *ConDecl) {
- assert(ConDecl && "Expected to receive a constructor declaration");
-
- // Check default arguments on the constructor
- CheckCXXDefaultArguments(ConDecl);
-
- // Set the lexical context of this constructor
- ConDecl->setLexicalDeclContext(CurContext);
-
- CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(ConDecl->getDeclContext());
-
- // Make sure this constructor is an overload of the existing
- // constructors.
- OverloadedFunctionDecl::function_iterator MatchedDecl;
- if (!IsOverload(ConDecl, ClassDecl->getConstructors(), MatchedDecl)) {
- if (CurContext == (*MatchedDecl)->getLexicalDeclContext()) {
- Diag(ConDecl->getLocation(), diag::err_constructor_redeclared)
- << SourceRange(ConDecl->getLocation());
- Diag((*MatchedDecl)->getLocation(), diag::note_previous_declaration)
- << SourceRange((*MatchedDecl)->getLocation());
- ConDecl->setInvalidDecl();
- return 0;
- }
-
- // FIXME: Just drop the definition (for now).
- return ConDecl;
- }
-
- // C++ [class.copy]p3:
- // A declaration of a constructor for a class X is ill-formed if
- // its first parameter is of type (optionally cv-qualified) X and
- // either there are no other parameters or else all other
- // parameters have default arguments.
- if ((ConDecl->getNumParams() == 1) ||
- (ConDecl->getNumParams() > 1 &&
- ConDecl->getParamDecl(1)->getDefaultArg() != 0)) {
- QualType ParamType = ConDecl->getParamDecl(0)->getType();
- QualType ClassTy = Context.getTagDeclType(
- const_cast<CXXRecordDecl*>(ConDecl->getParent()));
- if (Context.getCanonicalType(ParamType).getUnqualifiedType() == ClassTy) {
- Diag(ConDecl->getLocation(), diag::err_constructor_byvalue_arg)
- << SourceRange(ConDecl->getParamDecl(0)->getLocation());
- ConDecl->setInvalidDecl();
- return ConDecl;
- }
- }
-
- // Add this constructor to the set of constructors of the current
- // class.
- ClassDecl->addConstructor(Context, ConDecl);
- return (DeclTy *)ConDecl;
-}
-
-/// ActOnDestructorDeclarator - Called by ActOnDeclarator to complete
-/// the declaration of the given C++ @p Destructor. This routine is
-/// responsible for recording the destructor in the C++ class, if
-/// possible.
-Sema::DeclTy *Sema::ActOnDestructorDeclarator(CXXDestructorDecl *Destructor) {
- assert(Destructor && "Expected to receive a destructor declaration");
-
- CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Destructor->getDeclContext());
-
- // Set the lexical context of this destructor
- Destructor->setLexicalDeclContext(CurContext);
-
- // Make sure we aren't redeclaring the destructor.
- if (CXXDestructorDecl *PrevDestructor = ClassDecl->getDestructor()) {
- if (CurContext == PrevDestructor->getLexicalDeclContext()) {
- Diag(Destructor->getLocation(), diag::err_destructor_redeclared);
- Diag(PrevDestructor->getLocation(),
- PrevDestructor->isThisDeclarationADefinition() ?
- diag::note_previous_definition
- : diag::note_previous_declaration);
- Destructor->setInvalidDecl();
- }
-
- // FIXME: Just drop the definition (for now).
- return Destructor;
- }
-
- ClassDecl->setDestructor(Destructor);
- return (DeclTy *)Destructor;
-}
-
/// ActOnConversionDeclarator - Called by ActOnDeclarator to complete
/// the declaration of the given C++ conversion function. This routine
/// is responsible for recording the conversion function in the C++
@@ -1437,18 +1362,35 @@
OverloadCandidateSet CandidateSet;
// Add constructors to the overload set.
- OverloadedFunctionDecl *Constructors
- = const_cast<OverloadedFunctionDecl *>(ClassDecl->getConstructors());
- for (OverloadedFunctionDecl::function_iterator Con
- = Constructors->function_begin();
- Con != Constructors->function_end(); ++Con) {
- CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+ DeclarationName ConstructorName
+ = Context.DeclarationNames.getCXXConstructorName(
+ Context.getCanonicalType(ClassType.getUnqualifiedType()));
+ DeclContext::lookup_const_result Lookup
+ = ClassDecl->lookup(Context, ConstructorName);
+ if (Lookup.first == Lookup.second)
+ /* No constructors */;
+ else if (OverloadedFunctionDecl *Constructors
+ = dyn_cast<OverloadedFunctionDecl>(*Lookup.first)) {
+ for (OverloadedFunctionDecl::function_iterator Con
+ = Constructors->function_begin();
+ Con != Constructors->function_end(); ++Con) {
+ CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+ if ((Kind == IK_Direct) ||
+ (Kind == IK_Copy && Constructor->isConvertingConstructor()) ||
+ (Kind == IK_Default && Constructor->isDefaultConstructor()))
+ AddOverloadCandidate(Constructor, Args, NumArgs, CandidateSet);
+ }
+ } else if (CXXConstructorDecl *Constructor
+ = dyn_cast<CXXConstructorDecl>(*Lookup.first)) {
if ((Kind == IK_Direct) ||
(Kind == IK_Copy && Constructor->isConvertingConstructor()) ||
(Kind == IK_Default && Constructor->isDefaultConstructor()))
AddOverloadCandidate(Constructor, Args, NumArgs, CandidateSet);
}
+ // FIXME: When we decide not to synthesize the implicitly-declared
+ // constructors, we'll need to make them appear here.
+
OverloadCandidateSet::iterator Best;
switch (BestViableFunction(CandidateSet, Best)) {
case OR_Success:
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=61048&r1=61047&r2=61048&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon Dec 15 15:24:18 2008
@@ -953,11 +953,25 @@
// that class. The argument list is the expression-list within
// the parentheses of the initializer.
CXXRecordDecl *ToRecordDecl = ToRecordType->getDecl();
- const OverloadedFunctionDecl *Constructors = ToRecordDecl->getConstructors();
- for (OverloadedFunctionDecl::function_const_iterator func
- = Constructors->function_begin();
- func != Constructors->function_end(); ++func) {
- CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*func);
+ DeclarationName ConstructorName
+ = Context.DeclarationNames.getCXXConstructorName(
+ Context.getCanonicalType(ToType));
+ DeclContext::lookup_result Lookup
+ = ToRecordDecl->lookup(Context, ConstructorName);
+ if (Lookup.first == Lookup.second)
+ /* No constructors. FIXME: Implicit copy constructor? */;
+ else if (OverloadedFunctionDecl *Constructors
+ = dyn_cast<OverloadedFunctionDecl>(*Lookup.first)) {
+ for (OverloadedFunctionDecl::function_const_iterator func
+ = Constructors->function_begin();
+ func != Constructors->function_end(); ++func) {
+ CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*func);
+ if (Constructor->isConvertingConstructor())
+ AddOverloadCandidate(Constructor, &From, 1, CandidateSet,
+ /*SuppressUserConversions=*/true);
+ }
+ } else if (CXXConstructorDecl *Constructor
+ = dyn_cast<CXXConstructorDecl>(*Lookup.first)) {
if (Constructor->isConvertingConstructor())
AddOverloadCandidate(Constructor, &From, 1, CandidateSet,
/*SuppressUserConversions=*/true);
Modified: cfe/trunk/test/SemaCXX/constructor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constructor.cpp?rev=61048&r1=61047&r2=61048&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/constructor.cpp (original)
+++ cfe/trunk/test/SemaCXX/constructor.cpp Mon Dec 15 15:24:18 2008
@@ -21,3 +21,9 @@
Foo::Foo(const Foo&) { }
+typedef struct {
+ int version;
+} Anon;
+extern const Anon anon;
+extern "C" const Anon anon2;
+
Modified: cfe/trunk/test/SemaCXX/overload-decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overload-decl.cpp?rev=61048&r1=61047&r2=61048&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/overload-decl.cpp (original)
+++ cfe/trunk/test/SemaCXX/overload-decl.cpp Mon Dec 15 15:24:18 2008
@@ -13,11 +13,15 @@
void g(void); // expected-note {{previous declaration is here}}
int g(); // expected-error {{functions that differ only in their return type cannot be overloaded}}
+typedef int INT;
+
class X {
void f();
- void f(int);
+ void f(int); // expected-note {{previous declaration is here}}
void f() const;
+ void f(INT); // expected-error{{cannot be redeclared}}
+
void g(int); // expected-note {{previous declaration is here}}
void g(int, float); // expected-note {{previous declaration is here}}
int g(int, Float); // expected-error {{functions that differ only in their return type cannot be overloaded}}
More information about the cfe-commits
mailing list