summaryrefslogtreecommitdiffstats
path: root/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/SemaDecl.cpp12
-rw-r--r--lib/Sema/SemaDeclCXX.cpp42
-rw-r--r--lib/Sema/SemaDeclObjC.cpp5
-rw-r--r--lib/Sema/SemaExpr.cpp5
-rw-r--r--lib/Sema/SemaInit.cpp109
-rw-r--r--lib/Sema/SemaObjCProperty.cpp20
6 files changed, 79 insertions, 114 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index f3d0dcf..541c271 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -5740,17 +5740,15 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S,
Visibility != tok::objc_not_keyword ? TranslateIvarVisibility(Visibility)
: ObjCIvarDecl::None;
// Must set ivar's DeclContext to its enclosing interface.
- Decl *EnclosingDecl = IntfDecl.getAs<Decl>();
- DeclContext *EnclosingContext;
+ ObjCContainerDecl *EnclosingDecl = IntfDecl.getAs<ObjCContainerDecl>();
+ ObjCContainerDecl *EnclosingContext;
if (ObjCImplementationDecl *IMPDecl =
dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) {
// Case of ivar declared in an implementation. Context is that of its class.
- ObjCInterfaceDecl* IDecl = IMPDecl->getClassInterface();
- assert(IDecl && "No class- ActOnIvar");
- EnclosingContext = cast_or_null<DeclContext>(IDecl);
+ EnclosingContext = IMPDecl->getClassInterface();
+ assert(EnclosingContext && "Implementation has no class interface!");
} else
- EnclosingContext = dyn_cast<DeclContext>(EnclosingDecl);
- assert(EnclosingContext && "null DeclContext for ivar - ActOnIvar");
+ EnclosingContext = EnclosingDecl;
// Construct the decl.
ObjCIvarDecl *NewID = ObjCIvarDecl::Create(Context,
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 47df435..39e3739 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -3965,33 +3965,21 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
bool BaseInitialization) {
bool Elidable = false;
- // C++ [class.copy]p15:
- // Whenever a temporary class object is copied using a copy constructor, and
- // this object and the copy have the same cv-unqualified type, an
- // implementation is permitted to treat the original and the copy as two
- // different ways of referring to the same object and not perform a copy at
- // all, even if the class copy constructor or destructor have side effects.
-
- // FIXME: Is this enough?
- if (Constructor->isCopyConstructor()) {
- Expr *E = ((Expr **)ExprArgs.get())[0];
- if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
- if (ICE->getCastKind() == CastExpr::CK_NoOp)
- E = ICE->getSubExpr();
- if (CXXFunctionalCastExpr *FCE = dyn_cast<CXXFunctionalCastExpr>(E))
- E = FCE->getSubExpr();
- while (CXXBindTemporaryExpr *BE = dyn_cast<CXXBindTemporaryExpr>(E))
- E = BE->getSubExpr();
- if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
- if (ICE->getCastKind() == CastExpr::CK_NoOp)
- E = ICE->getSubExpr();
-
- if (CallExpr *CE = dyn_cast<CallExpr>(E))
- Elidable = !CE->getCallReturnType()->isReferenceType();
- else if (isa<CXXTemporaryObjectExpr>(E))
- Elidable = true;
- else if (isa<CXXConstructExpr>(E))
- Elidable = true;
+ // C++0x [class.copy]p34:
+ // When certain criteria are met, an implementation is allowed to
+ // omit the copy/move construction of a class object, even if the
+ // copy/move constructor and/or destructor for the object have
+ // side effects. [...]
+ // - when a temporary class object that has not been bound to a
+ // reference (12.2) would be copied/moved to a class object
+ // with the same cv-unqualified type, the copy/move operation
+ // can be omitted by constructing the temporary object
+ // directly into the target of the omitted copy/move
+ if (Constructor->isCopyConstructor() && ExprArgs.size() >= 1) {
+ Expr *SubExpr = ((Expr **)ExprArgs.get())[0];
+ Elidable = SubExpr->isTemporaryObject() &&
+ Context.hasSameUnqualifiedType(SubExpr->getType(),
+ Context.getTypeDeclType(Constructor->getParent()));
}
return BuildCXXConstructExpr(ConstructLoc, DeclInitType, Constructor,
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 9bc0846..0c47e63 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -431,6 +431,11 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
// Class extensions require a special treatment. Use an existing one.
// Note that 'getClassExtension()' can return NULL.
CDecl = IDecl->getClassExtension();
+ if (IDecl->getImplementation()) {
+ Diag(ClassLoc, diag::err_class_extension_after_impl) << ClassName;
+ Diag(IDecl->getImplementation()->getLocation(),
+ diag::note_implementation_declared);
+ }
}
if (!CDecl) {
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index fbdf080..2dfb954 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -1345,11 +1345,6 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
}
}
}
- if (LangOpts.ObjCNonFragileABI2 && LookForIvars && Lookup.empty()) {
- ObjCIvarDecl *Ivar = SynthesizeNewPropertyIvar(IFace, II);
- if (Ivar)
- return LookupInObjCMethod(Lookup, S, II, AllowBuiltinCreation);
- }
// Sentinel value saying that we didn't do anything special.
return Owned((Expr*) 0);
}
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 648e43b..1d0575c 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -2583,10 +2583,7 @@ static void TryConstructorInitialization(Sema &S,
Expr **Args, unsigned NumArgs,
QualType DestType,
InitializationSequence &Sequence) {
- if (Kind.getKind() == InitializationKind::IK_Copy)
- Sequence.setSequenceKind(InitializationSequence::UserDefinedConversion);
- else
- Sequence.setSequenceKind(InitializationSequence::ConstructorInitialization);
+ Sequence.setSequenceKind(InitializationSequence::ConstructorInitialization);
// Build the candidate set directly in the initialization sequence
// structure, so that it will persist if we fail.
@@ -2597,7 +2594,7 @@ static void TryConstructorInitialization(Sema &S,
// explicit conversion operators.
bool AllowExplicit = (Kind.getKind() == InitializationKind::IK_Direct ||
Kind.getKind() == InitializationKind::IK_Value ||
- Kind.getKind() == InitializationKind::IK_Default);
+ Kind.getKind() == InitializationKind::IK_Default);
// The type we're converting to is a class type. Enumerate its constructors
// to see if one is suitable.
@@ -2661,14 +2658,10 @@ static void TryConstructorInitialization(Sema &S,
// Add the constructor initialization step. Any cv-qualification conversion is
// subsumed by the initialization.
- if (Kind.getKind() == InitializationKind::IK_Copy) {
- Sequence.AddUserConversionStep(Best->Function, Best->FoundDecl, DestType);
- } else {
- Sequence.AddConstructorInitializationStep(
+ Sequence.AddConstructorInitializationStep(
cast<CXXConstructorDecl>(Best->Function),
Best->FoundDecl.getAccess(),
DestType);
- }
}
/// \brief Attempt value initialization (C++ [dcl.init]p7).
@@ -3085,14 +3078,11 @@ getAssignmentAction(const InitializedEntity &Entity) {
return Sema::AA_Converting;
}
-static bool shouldBindAsTemporary(const InitializedEntity &Entity,
- bool IsCopy) {
+static bool shouldBindAsTemporary(const InitializedEntity &Entity) {
switch (Entity.getKind()) {
- case InitializedEntity::EK_Result:
case InitializedEntity::EK_ArrayElement:
case InitializedEntity::EK_Member:
- return !IsCopy;
-
+ case InitializedEntity::EK_Result:
case InitializedEntity::EK_New:
case InitializedEntity::EK_Variable:
case InitializedEntity::EK_Base:
@@ -3108,21 +3098,38 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity,
llvm_unreachable("missed an InitializedEntity kind?");
}
-/// \brief If we need to perform an additional copy of the initialized object
-/// for this kind of entity (e.g., the result of a function or an object being
-/// thrown), make the copy.
-static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S,
- const InitializedEntity &Entity,
- const InitializationKind &Kind,
- Sema::OwningExprResult CurInit) {
+static Sema::OwningExprResult CopyObject(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ Sema::OwningExprResult CurInit) {
+ // Determine which class type we're copying.
Expr *CurInitExpr = (Expr *)CurInit.get();
-
+ CXXRecordDecl *Class = 0;
+ if (const RecordType *Record = CurInitExpr->getType()->getAs<RecordType>())
+ Class = cast<CXXRecordDecl>(Record->getDecl());
+ if (!Class)
+ return move(CurInit);
+
+ // C++0x [class.copy]p34:
+ // When certain criteria are met, an implementation is allowed to
+ // omit the copy/move construction of a class object, even if the
+ // copy/move constructor and/or destructor for the object have
+ // side effects. [...]
+ // - when a temporary class object that has not been bound to a
+ // reference (12.2) would be copied/moved to a class object
+ // with the same cv-unqualified type, the copy/move operation
+ // can be omitted by constructing the temporary object
+ // directly into the target of the omitted copy/move
+ //
+ // Note that the other three bullets are handled elsewhere. Copy
+ // elision for return statements and throw expressions are (FIXME:
+ // not yet) handled as part of constructor initialization, while
+ // copy elision for exception handlers is handled by the run-time.
+ bool Elidable = CurInitExpr->isTemporaryObject() &&
+ S.Context.hasSameUnqualifiedType(Entity.getType(), CurInitExpr->getType());
SourceLocation Loc;
-
switch (Entity.getKind()) {
case InitializedEntity::EK_Result:
- if (Entity.getType()->isReferenceType())
- return move(CurInit);
Loc = Entity.getReturnLoc();
break;
@@ -3131,38 +3138,20 @@ static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S,
break;
case InitializedEntity::EK_Variable:
- if (Entity.getType()->isReferenceType() ||
- Kind.getKind() != InitializationKind::IK_Copy)
- return move(CurInit);
Loc = Entity.getDecl()->getLocation();
break;
case InitializedEntity::EK_ArrayElement:
case InitializedEntity::EK_Member:
- if (Entity.getType()->isReferenceType() ||
- Kind.getKind() != InitializationKind::IK_Copy)
- return move(CurInit);
- Loc = CurInitExpr->getLocStart();
- break;
-
case InitializedEntity::EK_Parameter:
- // FIXME: Do we need this initialization for a parameter?
- return move(CurInit);
-
- case InitializedEntity::EK_New:
case InitializedEntity::EK_Temporary:
+ case InitializedEntity::EK_New:
case InitializedEntity::EK_Base:
case InitializedEntity::EK_VectorElement:
- // We don't need to copy for any of these initialized entities.
- return move(CurInit);
+ Loc = CurInitExpr->getLocStart();
+ break;
}
-
- CXXRecordDecl *Class = 0;
- if (const RecordType *Record = CurInitExpr->getType()->getAs<RecordType>())
- Class = cast<CXXRecordDecl>(Record->getDecl());
- if (!Class)
- return move(CurInit);
-
+
// Perform overload resolution using the class's copy constructors.
DeclarationName ConstructorName
= S.Context.DeclarationNames.getCXXConstructorName(
@@ -3171,7 +3160,7 @@ static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S,
OverloadCandidateSet CandidateSet(Loc);
for (llvm::tie(Con, ConEnd) = Class->lookup(ConstructorName);
Con != ConEnd; ++Con) {
- // Find the constructor (which may be a template).
+ // Only consider copy constructors.
CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(*Con);
if (!Constructor || Constructor->isInvalidDecl() ||
!Constructor->isCopyConstructor())
@@ -3181,7 +3170,7 @@ static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S,
= DeclAccessPair::make(Constructor, Constructor->getAccess());
S.AddOverloadCandidate(Constructor, FoundDecl,
&CurInitExpr, 1, CandidateSet);
- }
+ }
OverloadCandidateSet::iterator Best;
switch (S.BestViableFunction(CandidateSet, Loc, Best)) {
@@ -3218,9 +3207,9 @@ static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S,
Best->FoundDecl.getAccess());
CurInit.release();
- return S.BuildCXXConstructExpr(Loc, CurInitExpr->getType(),
+ return S.BuildCXXConstructExpr(Loc, Entity.getType().getNonReferenceType(),
cast<CXXConstructorDecl>(Best->Function),
- /*Elidable=*/true,
+ Elidable,
Sema::MultiExprArg(S,
(void**)&CurInitExpr, 1));
}
@@ -3474,7 +3463,9 @@ InitializationSequence::Perform(Sema &S,
CastKind = CastExpr::CK_UserDefinedConversion;
}
- if (shouldBindAsTemporary(Entity, IsCopy))
+ bool RequiresCopy = !IsCopy &&
+ getKind() != InitializationSequence::ReferenceBinding;
+ if (RequiresCopy || shouldBindAsTemporary(Entity))
CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
CurInitExpr = CurInit.takeAs<Expr>();
@@ -3483,8 +3474,8 @@ InitializationSequence::Perform(Sema &S,
CurInitExpr,
IsLvalue));
- if (!IsCopy)
- CurInit = CopyIfRequiredForEntity(S, Entity, Kind, move(CurInit));
+ if (RequiresCopy)
+ CurInit = CopyObject(S, Entity, Kind, move(CurInit));
break;
}
@@ -3560,13 +3551,9 @@ InitializationSequence::Perform(Sema &S,
S.CheckConstructorAccess(Loc, Constructor,
Step->Function.FoundDecl.getAccess());
- bool Elidable
- = cast<CXXConstructExpr>((Expr *)CurInit.get())->isElidable();
- if (shouldBindAsTemporary(Entity, Elidable))
+ if (shouldBindAsTemporary(Entity))
CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
-
- if (!Elidable)
- CurInit = CopyIfRequiredForEntity(S, Entity, Kind, move(CurInit));
+
break;
}
diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp
index f815068..52b9bcf 100644
--- a/lib/Sema/SemaObjCProperty.cpp
+++ b/lib/Sema/SemaObjCProperty.cpp
@@ -281,7 +281,7 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(SourceLocation AtLoc,
DeclPtrTy ClassCatImpDecl,
IdentifierInfo *PropertyId,
IdentifierInfo *PropertyIvar) {
- Decl *ClassImpDecl = ClassCatImpDecl.getAs<Decl>();
+ ObjCContainerDecl *ClassImpDecl = ClassCatImpDecl.getAs<ObjCContainerDecl>();
// Make sure we have a context for the property implementation declaration.
if (!ClassImpDecl) {
Diag(AtLoc, diag::error_missing_property_context);
@@ -353,14 +353,11 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(SourceLocation AtLoc,
ObjCInterfaceDecl *ClassDeclared;
Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared);
if (!Ivar) {
- DeclContext *EnclosingContext = cast_or_null<DeclContext>(ClassImpDecl);
- assert(EnclosingContext &&
- "null DeclContext for synthesized ivar - ActOnPropertyImplDecl");
- Ivar = ObjCIvarDecl::Create(Context, EnclosingContext, PropertyLoc,
+ Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl, PropertyLoc,
PropertyIvar, PropType, /*Dinfo=*/0,
ObjCIvarDecl::Public,
(Expr *)0);
- EnclosingContext->addDecl(Ivar);
+ ClassImpDecl->addDecl(Ivar);
IDecl->makeDeclVisibleInContext(Ivar, false);
property->setPropertyIvarDecl(Ivar);
@@ -1072,15 +1069,10 @@ Sema::SynthesizeNewPropertyIvar(ObjCInterfaceDecl *IDecl,
ObjCIvarDecl *Ivar = 0;
ObjCPropertyDecl *Prop = LookupPropertyDecl(IDecl, NameII);
if (Prop && !Prop->isInvalidDecl()) {
- DeclContext *EnclosingContext = cast_or_null<DeclContext>(IDecl);
QualType PropType = Context.getCanonicalType(Prop->getType());
- assert(EnclosingContext &&
- "null DeclContext for synthesized ivar - SynthesizeNewPropertyIvar");
- Ivar = ObjCIvarDecl::Create(Context, EnclosingContext,
- Prop->getLocation(),
- NameII, PropType, /*Dinfo=*/0,
- ObjCIvarDecl::Public,
- (Expr *)0);
+ Ivar = ObjCIvarDecl::Create(Context, IDecl, Prop->getLocation(), NameII,
+ PropType, /*Dinfo=*/0,
+ ObjCIvarDecl::Public, (Expr *)0);
Ivar->setLexicalDeclContext(IDecl);
IDecl->addDecl(Ivar);
Prop->setPropertyIvarDecl(Ivar);
OpenPOWER on IntegriCloud