aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDeclCXX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaDeclCXX.cpp')
-rw-r--r--lib/Sema/SemaDeclCXX.cpp168
1 files changed, 110 insertions, 58 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index cf0dab5cf298..75ceb1916555 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -258,6 +258,12 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) {
}
}
+ if (CheckEquivalentExceptionSpec(
+ Old->getType()->getAsFunctionProtoType(), Old->getLocation(),
+ New->getType()->getAsFunctionProtoType(), New->getLocation())) {
+ Invalid = true;
+ }
+
return Invalid;
}
@@ -481,7 +487,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
}
// Attach the remaining base class specifiers to the derived class.
- Class->setBases(Bases, NumGoodBases);
+ Class->setBases(Context, Bases, NumGoodBases);
// Delete the remaining (good) base class specifiers, since their
// data has been copied into the CXXRecordDecl.
@@ -646,7 +652,9 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
Sema::MemInitResult
Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
Scope *S,
+ const CXXScopeSpec &SS,
IdentifierInfo *MemberOrBase,
+ TypeTy *TemplateTypeTy,
SourceLocation IdLoc,
SourceLocation LParenLoc,
ExprTy **Args, unsigned NumArgs,
@@ -677,28 +685,31 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
// composed of a single identifier refers to the class member. A
// mem-initializer-id for the hidden base class may be specified
// using a qualified name. ]
- // Look for a member, first.
- FieldDecl *Member = 0;
- DeclContext::lookup_result Result
- = ClassDecl->lookup(Context, MemberOrBase);
- if (Result.first != Result.second)
- Member = dyn_cast<FieldDecl>(*Result.first);
-
- // FIXME: Handle members of an anonymous union.
-
- if (Member) {
- // FIXME: Perform direct initialization of the member.
- return new CXXBaseOrMemberInitializer(Member, (Expr **)Args, NumArgs);
+ if (!SS.getScopeRep() && !TemplateTypeTy) {
+ // Look for a member, first.
+ FieldDecl *Member = 0;
+ DeclContext::lookup_result Result
+ = ClassDecl->lookup(MemberOrBase);
+ if (Result.first != Result.second)
+ Member = dyn_cast<FieldDecl>(*Result.first);
+
+ // FIXME: Handle members of an anonymous union.
+
+ if (Member) {
+ // FIXME: Perform direct initialization of the member.
+ return new CXXBaseOrMemberInitializer(Member, (Expr **)Args, NumArgs,
+ IdLoc);
+ }
}
-
// It didn't name a member, so see if it names a class.
- TypeTy *BaseTy = getTypeName(*MemberOrBase, IdLoc, S, 0/*SS*/);
+ TypeTy *BaseTy = TemplateTypeTy ? TemplateTypeTy
+ : getTypeName(*MemberOrBase, IdLoc, S, &SS);
if (!BaseTy)
return Diag(IdLoc, diag::err_mem_init_not_member_or_class)
<< MemberOrBase << SourceRange(IdLoc, RParenLoc);
QualType BaseType = QualType::getFromOpaquePtr(BaseTy);
- if (!BaseType->isRecordType())
+ if (!BaseType->isRecordType() && !BaseType->isDependentType())
return Diag(IdLoc, diag::err_base_init_does_not_name_class)
<< BaseType << SourceRange(IdLoc, RParenLoc);
@@ -749,8 +760,18 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
if (DirectBaseSpec && VirtualBaseSpec)
return Diag(IdLoc, diag::err_base_init_direct_and_virtual)
<< MemberOrBase << SourceRange(IdLoc, RParenLoc);
+ // C++ [base.class.init]p2:
+ // Unless the mem-initializer-id names a nonstatic data membeer of the
+ // constructor's class ot a direst or virtual base of that class, the
+ // mem-initializer is ill-formed.
+ if (!DirectBaseSpec && !VirtualBaseSpec)
+ return Diag(IdLoc, diag::err_not_direct_base_or_virtual)
+ << BaseType << ClassDecl->getNameAsCString()
+ << SourceRange(IdLoc, RParenLoc);
+
- return new CXXBaseOrMemberInitializer(BaseType, (Expr **)Args, NumArgs);
+ return new CXXBaseOrMemberInitializer(BaseType, (Expr **)Args, NumArgs,
+ IdLoc);
}
void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
@@ -766,6 +787,42 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
Diag(ColonLoc, diag::err_only_constructors_take_base_inits);
return;
}
+ llvm::DenseMap<void*, CXXBaseOrMemberInitializer *>Members;
+ bool err = false;
+ for (unsigned i = 0; i < NumMemInits; i++) {
+ CXXBaseOrMemberInitializer *Member =
+ static_cast<CXXBaseOrMemberInitializer*>(MemInits[i]);
+ void *KeyToMember = Member->getBaseOrMember();
+ // For fields injected into the class via declaration of an anonymous union,
+ // use its anonymous union class declaration as the unique key.
+ if (FieldDecl *Field = Member->getMember())
+ if (Field->getDeclContext()->isRecord() &&
+ cast<RecordDecl>(Field->getDeclContext())->isAnonymousStructOrUnion())
+ KeyToMember = static_cast<void *>(Field->getDeclContext());
+ CXXBaseOrMemberInitializer *&PrevMember = Members[KeyToMember];
+ if (!PrevMember) {
+ PrevMember = Member;
+ continue;
+ }
+ if (FieldDecl *Field = Member->getMember())
+ Diag(Member->getSourceLocation(),
+ diag::error_multiple_mem_initialization)
+ << Field->getNameAsString();
+ else {
+ Type *BaseClass = Member->getBaseClass();
+ assert(BaseClass && "ActOnMemInitializers - neither field or base");
+ Diag(Member->getSourceLocation(),
+ diag::error_multiple_base_initialization)
+ << BaseClass->getDesugaredType(true);
+ }
+ Diag(PrevMember->getSourceLocation(), diag::note_previous_initializer)
+ << 0;
+ err = true;
+ }
+ if (!err)
+ Constructor->setBaseOrMemberInitializers(Context,
+ reinterpret_cast<CXXBaseOrMemberInitializer **>(MemInits),
+ NumMemInits);
}
namespace {
@@ -821,8 +878,7 @@ namespace {
MethodSetTy OverriddenMethods;
size_t MethodsSize = Methods.size();
- for (RecordDecl::decl_iterator i = RD->decls_begin(Context),
- e = RD->decls_end(Context);
+ for (RecordDecl::decl_iterator i = RD->decls_begin(), e = RD->decls_end();
i != e; ++i) {
// Traverse the record, looking for methods.
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*i)) {
@@ -919,8 +975,8 @@ namespace {
bool VisitDeclContext(const DeclContext *DC) {
bool Invalid = false;
- for (CXXRecordDecl::decl_iterator I = DC->decls_begin(SemaRef.Context),
- E = DC->decls_end(SemaRef.Context); I != E; ++I)
+ for (CXXRecordDecl::decl_iterator I = DC->decls_begin(),
+ E = DC->decls_end(); I != E; ++I)
Invalid |= Visit(*I);
return Invalid;
@@ -996,8 +1052,8 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
AbstractClassUsageDiagnoser(*this, RD);
if (RD->hasTrivialConstructor() || RD->hasTrivialDestructor()) {
- for (RecordDecl::field_iterator i = RD->field_begin(Context),
- e = RD->field_end(Context); i != e; ++i) {
+ for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
+ i != e; ++i) {
// All the nonstatic data members must have trivial constructors.
QualType FTy = i->getType();
while (const ArrayType *AT = Context.getAsArrayType(FTy))
@@ -1054,7 +1110,7 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
/*isImplicitlyDeclared=*/true);
DefaultCon->setAccess(AS_public);
DefaultCon->setImplicit();
- ClassDecl->addDecl(Context, DefaultCon);
+ ClassDecl->addDecl(DefaultCon);
}
if (!ClassDecl->hasUserDeclaredCopyConstructor()) {
@@ -1086,8 +1142,8 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
// class type M (or array thereof), each such class type
// has a copy constructor whose first parameter is of type
// const M& or const volatile M&.
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(Context);
- HasConstCopyConstructor && Field != ClassDecl->field_end(Context);
+ for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin();
+ HasConstCopyConstructor && Field != ClassDecl->field_end();
++Field) {
QualType FieldType = (*Field)->getType();
if (const ArrayType *Array = Context.getAsArrayType(FieldType))
@@ -1131,7 +1187,7 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
/*IdentifierInfo=*/0,
ArgType, VarDecl::None, 0);
CopyConstructor->setParams(Context, &FromParam, 1);
- ClassDecl->addDecl(Context, CopyConstructor);
+ ClassDecl->addDecl(CopyConstructor);
}
if (!ClassDecl->hasUserDeclaredCopyAssignment()) {
@@ -1165,8 +1221,8 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
// type M (or array thereof), each such class type has a copy
// assignment operator whose parameter is of type const M&,
// const volatile M& or M.
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(Context);
- HasConstCopyAssignment && Field != ClassDecl->field_end(Context);
+ for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin();
+ HasConstCopyAssignment && Field != ClassDecl->field_end();
++Field) {
QualType FieldType = (*Field)->getType();
if (const ArrayType *Array = Context.getAsArrayType(FieldType))
@@ -1210,7 +1266,7 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
// Don't call addedAssignmentOperator. There is no way to distinguish an
// implicit from an explicit assignment operator.
- ClassDecl->addDecl(Context, CopyAssignment);
+ ClassDecl->addDecl(CopyAssignment);
}
if (!ClassDecl->hasUserDeclaredDestructor()) {
@@ -1229,7 +1285,7 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
/*isImplicitlyDeclared=*/true);
Destructor->setAccess(AS_public);
Destructor->setImplicit();
- ClassDecl->addDecl(Context, Destructor);
+ ClassDecl->addDecl(Destructor);
}
}
@@ -1772,7 +1828,7 @@ void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) {
// or translation unit scope. We add UsingDirectiveDecls, into
// it's lookup structure.
if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity()))
- Ctx->addDecl(Context, UDir);
+ Ctx->addDecl(UDir);
else
// Otherwise it is block-sope. using-directives will affect lookup
// only to the end of scope.
@@ -1873,7 +1929,7 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S,
(NestedNameSpecifier *)SS.getScopeRep(),
IdentLoc, R);
- CurContext->addDecl(Context, AliasDecl);
+ CurContext->addDecl(AliasDecl);
return DeclPtrTy::make(AliasDecl);
}
@@ -1891,8 +1947,8 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
// for its base class and its non-static data members shall have been
// implicitly defined.
bool err = false;
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
- Base != ClassDecl->bases_end(); ++Base) {
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+ E = ClassDecl->bases_end(); Base != E; ++Base) {
CXXRecordDecl *BaseClassDecl
= cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl());
if (!BaseClassDecl->hasTrivialConstructor()) {
@@ -1909,9 +1965,8 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
}
}
}
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(Context);
- Field != ClassDecl->field_end(Context);
- ++Field) {
+ for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+ E = ClassDecl->field_end(); Field != E; ++Field) {
QualType FieldType = Context.getCanonicalType((*Field)->getType());
if (const ArrayType *Array = Context.getAsArrayType(FieldType))
FieldType = Array->getElementType();
@@ -1964,8 +2019,8 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
// implicitly defined, all the implicitly-declared default destructors
// for its base class and its non-static data members shall have been
// implicitly defined.
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
- Base != ClassDecl->bases_end(); ++Base) {
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+ E = ClassDecl->bases_end(); Base != E; ++Base) {
CXXRecordDecl *BaseClassDecl
= cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl());
if (!BaseClassDecl->hasTrivialDestructor()) {
@@ -1978,9 +2033,8 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
}
}
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(Context);
- Field != ClassDecl->field_end(Context);
- ++Field) {
+ for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+ E = ClassDecl->field_end(); Field != E; ++Field) {
QualType FieldType = Context.getCanonicalType((*Field)->getType());
if (const ArrayType *Array = Context.getAsArrayType(FieldType))
FieldType = Array->getElementType();
@@ -2010,7 +2064,6 @@ void Sema::DefineImplicitOverloadedAssign(SourceLocation CurrentLocation,
CXXRecordDecl *ClassDecl
= cast<CXXRecordDecl>(MethodDecl->getDeclContext());
- assert(ClassDecl && "DefineImplicitOverloadedAssign - invalid constructor");
// C++[class.copy] p12
// Before the implicitly-declared copy assignment operator for a class is
@@ -2018,17 +2071,16 @@ void Sema::DefineImplicitOverloadedAssign(SourceLocation CurrentLocation,
// for its direct base classes and its nonstatic data members shall have
// been implicitly defined.
bool err = false;
- for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
- Base != ClassDecl->bases_end(); ++Base) {
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+ E = ClassDecl->bases_end(); Base != E; ++Base) {
CXXRecordDecl *BaseClassDecl
= cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl());
if (CXXMethodDecl *BaseAssignOpMethod =
getAssignOperatorMethod(MethodDecl->getParamDecl(0), BaseClassDecl))
MarkDeclarationReferenced(CurrentLocation, BaseAssignOpMethod);
}
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(Context);
- Field != ClassDecl->field_end(Context);
- ++Field) {
+ for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+ E = ClassDecl->field_end(); Field != E; ++Field) {
QualType FieldType = Context.getCanonicalType((*Field)->getType());
if (const ArrayType *Array = Context.getAsArrayType(FieldType))
FieldType = Array->getElementType();
@@ -2113,9 +2165,9 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
BaseClassDecl->getCopyConstructor(Context, TypeQuals))
MarkDeclarationReferenced(CurrentLocation, BaseCopyCtor);
}
- for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(Context);
- Field != ClassDecl->field_end(Context);
- ++Field) {
+ for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+ FieldEnd = ClassDecl->field_end();
+ Field != FieldEnd; ++Field) {
QualType FieldType = Context.getCanonicalType((*Field)->getType());
if (const ArrayType *Array = Context.getAsArrayType(FieldType))
FieldType = Array->getElementType();
@@ -2140,7 +2192,7 @@ void Sema::InitializeVarWithConstructor(VarDecl *VD,
VD->setInit(Context, Temp);
}
-void Sema::MarcDestructorReferenced(SourceLocation Loc, QualType DeclInitType)
+void Sema::MarkDestructorReferenced(SourceLocation Loc, QualType DeclInitType)
{
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(
DeclInitType->getAsRecordType()->getDecl());
@@ -2218,7 +2270,7 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
(Expr**)Exprs.release(), NumExprs);
// FIXME. Must do all that is needed to destroy the object
// on scope exit. For now, just mark the destructor as used.
- MarcDestructorReferenced(VDecl->getLocation(), DeclInitType);
+ MarkDestructorReferenced(VDecl->getLocation(), DeclInitType);
}
return;
}
@@ -2282,7 +2334,7 @@ Sema::PerformInitializationByConstructor(QualType ClassType,
= Context.DeclarationNames.getCXXConstructorName(
Context.getCanonicalType(ClassType.getUnqualifiedType()));
DeclContext::lookup_const_iterator Con, ConEnd;
- for (llvm::tie(Con, ConEnd) = ClassDecl->lookup(Context, ConstructorName);
+ for (llvm::tie(Con, ConEnd) = ClassDecl->lookup(ConstructorName);
Con != ConEnd; ++Con) {
CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
if ((Kind == IK_Direct) ||
@@ -2892,7 +2944,7 @@ Sema::DeclPtrTy Sema::ActOnStartLinkageSpecification(Scope *S,
LinkageSpecDecl *D = LinkageSpecDecl::Create(Context, CurContext,
LangLoc, Language,
LBraceLoc.isValid());
- CurContext->addDecl(Context, D);
+ CurContext->addDecl(D);
PushDeclContext(S, D);
return DeclPtrTy::make(D);
}
@@ -3006,7 +3058,7 @@ Sema::DeclPtrTy Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
if (II)
PushOnScopeChains(ExDecl, S);
else
- CurContext->addDecl(Context, ExDecl);
+ CurContext->addDecl(ExDecl);
ProcessDeclAttributes(S, ExDecl, D);
return DeclPtrTy::make(ExDecl);
@@ -3040,7 +3092,7 @@ Sema::DeclPtrTy Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
Decl *Decl = StaticAssertDecl::Create(Context, CurContext, AssertLoc,
AssertExpr, AssertMessage);
- CurContext->addDecl(Context, Decl);
+ CurContext->addDecl(Decl);
return DeclPtrTy::make(Decl);
}