diff options
-rw-r--r-- | include/clang/Sema/Sema.h | 20 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 38 | ||||
-rw-r--r-- | lib/Sema/SemaObjCProperty.cpp | 25 | ||||
-rw-r--r-- | test/SemaObjCXX/property-synthesis-error.mm | 21 |
4 files changed, 64 insertions, 40 deletions
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index a4affbb431..15303ef817 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -466,6 +466,26 @@ public: } }; + /// \brief RAII object to handle the state changes required to synthesize + /// a function body. + class SynthesizedFunctionScope { + Sema &S; + Sema::ContextRAII SavedContext; + + public: + SynthesizedFunctionScope(Sema &S, DeclContext *DC) + : S(S), SavedContext(S, DC) + { + S.PushFunctionScope(); + S.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated); + } + + ~SynthesizedFunctionScope() { + S.PopExpressionEvaluationContext(); + S.PopFunctionScopeInfo(); + } + }; + /// WeakUndeclaredIdentifiers - Identifiers contained in /// \#pragma weak before declared. rare. may alias another /// identifier, declared or undeclared diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 357f338f11..93b78c1316 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -6816,28 +6816,6 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, return AliasDecl; } -namespace { - /// \brief Scoped object used to handle the state changes required in Sema - /// to implicitly define the body of a C++ member function; - class ImplicitlyDefinedFunctionScope { - Sema &S; - Sema::ContextRAII SavedContext; - - public: - ImplicitlyDefinedFunctionScope(Sema &S, CXXMethodDecl *Method) - : S(S), SavedContext(S, Method) - { - S.PushFunctionScope(); - S.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated); - } - - ~ImplicitlyDefinedFunctionScope() { - S.PopExpressionEvaluationContext(); - S.PopFunctionScopeInfo(); - } - }; -} - Sema::ImplicitExceptionSpecification Sema::ComputeDefaultedDefaultCtorExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD) { @@ -6981,7 +6959,7 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, CXXRecordDecl *ClassDecl = Constructor->getParent(); assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor"); - ImplicitlyDefinedFunctionScope Scope(*this, Constructor); + SynthesizedFunctionScope Scope(*this, Constructor); DiagnosticErrorTrap Trap(Diags); if (SetCtorInitializers(Constructor, 0, 0, /*AnyErrors=*/false) || Trap.hasErrorOccurred()) { @@ -7293,7 +7271,7 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, if (Destructor->isInvalidDecl()) return; - ImplicitlyDefinedFunctionScope Scope(*this, Destructor); + SynthesizedFunctionScope Scope(*this, Destructor); DiagnosticErrorTrap Trap(Diags); MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(), @@ -7774,7 +7752,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, CopyAssignOperator->setUsed(); - ImplicitlyDefinedFunctionScope Scope(*this, CopyAssignOperator); + SynthesizedFunctionScope Scope(*this, CopyAssignOperator); DiagnosticErrorTrap Trap(Diags); // C++0x [class.copy]p30: @@ -8315,7 +8293,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, MoveAssignOperator->setUsed(); - ImplicitlyDefinedFunctionScope Scope(*this, MoveAssignOperator); + SynthesizedFunctionScope Scope(*this, MoveAssignOperator); DiagnosticErrorTrap Trap(Diags); // C++0x [class.copy]p28: @@ -8811,7 +8789,7 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, CXXRecordDecl *ClassDecl = CopyConstructor->getParent(); assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor"); - ImplicitlyDefinedFunctionScope Scope(*this, CopyConstructor); + SynthesizedFunctionScope Scope(*this, CopyConstructor); DiagnosticErrorTrap Trap(Diags); if (SetCtorInitializers(CopyConstructor, 0, 0, /*AnyErrors=*/false) || @@ -8994,7 +8972,7 @@ void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation, CXXRecordDecl *ClassDecl = MoveConstructor->getParent(); assert(ClassDecl && "DefineImplicitMoveConstructor - invalid constructor"); - ImplicitlyDefinedFunctionScope Scope(*this, MoveConstructor); + SynthesizedFunctionScope Scope(*this, MoveConstructor); DiagnosticErrorTrap Trap(Diags); if (SetCtorInitializers(MoveConstructor, 0, 0, /*AnyErrors=*/false) || @@ -9046,7 +9024,7 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion( Conv->setUsed(); - ImplicitlyDefinedFunctionScope Scope(*this, Conv); + SynthesizedFunctionScope Scope(*this, Conv); DiagnosticErrorTrap Trap(Diags); // Return the address of the __invoke function. @@ -9079,7 +9057,7 @@ void Sema::DefineImplicitLambdaToBlockPointerConversion( { Conv->setUsed(); - ImplicitlyDefinedFunctionScope Scope(*this, Conv); + SynthesizedFunctionScope Scope(*this, Conv); DiagnosticErrorTrap Trap(Diags); // Copy-initialize the lambda object as needed to capture it. diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index 6ed6d00d2e..de608a129f 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -1028,19 +1028,21 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, // For Objective-C++, need to synthesize the AST for the IVAR object to be // returned by the getter as it must conform to C++'s copy-return rules. // FIXME. Eventually we want to do this for Objective-C as well. + SynthesizedFunctionScope Scope(*this, getterMethod); ImplicitParamDecl *SelfDecl = getterMethod->getSelfDecl(); DeclRefExpr *SelfExpr = new (Context) DeclRefExpr(SelfDecl, false, SelfDecl->getType(), - VK_RValue, SourceLocation()); + VK_RValue, PropertyDiagLoc); + MarkDeclRefReferenced(SelfExpr); Expr *IvarRefExpr = - new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), AtLoc, + new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), PropertyDiagLoc, SelfExpr, true, true); ExprResult Res = PerformCopyInitialization(InitializedEntity::InitializeResult( - SourceLocation(), + PropertyDiagLoc, getterMethod->getResultType(), /*NRVO=*/false), - SourceLocation(), + PropertyDiagLoc, Owned(IvarRefExpr)); if (!Res.isInvalid()) { Expr *ResExpr = Res.takeAs<Expr>(); @@ -1061,19 +1063,22 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, if (getLangOpts().CPlusPlus && Synthesize && !CompleteTypeErr && Ivar->getType()->isRecordType()) { // FIXME. Eventually we want to do this for Objective-C as well. + SynthesizedFunctionScope Scope(*this, setterMethod); ImplicitParamDecl *SelfDecl = setterMethod->getSelfDecl(); DeclRefExpr *SelfExpr = new (Context) DeclRefExpr(SelfDecl, false, SelfDecl->getType(), - VK_RValue, SourceLocation()); + VK_RValue, PropertyDiagLoc); + MarkDeclRefReferenced(SelfExpr); Expr *lhs = - new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), AtLoc, + new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), PropertyDiagLoc, SelfExpr, true, true); ObjCMethodDecl::param_iterator P = setterMethod->param_begin(); ParmVarDecl *Param = (*P); QualType T = Param->getType().getNonReferenceType(); - Expr *rhs = new (Context) DeclRefExpr(Param, false, T, - VK_LValue, SourceLocation()); - ExprResult Res = BuildBinOp(S, lhs->getLocEnd(), + DeclRefExpr *rhs = new (Context) DeclRefExpr(Param, false, T, + VK_LValue, PropertyDiagLoc); + MarkDeclRefReferenced(rhs); + ExprResult Res = BuildBinOp(S, PropertyDiagLoc, BO_Assign, lhs, rhs); if (property->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_atomic) { @@ -1083,7 +1088,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, if (const FunctionDecl *FuncDecl = CXXCE->getDirectCallee()) if (!FuncDecl->isTrivial()) if (property->getType()->isReferenceType()) { - Diag(PropertyLoc, + Diag(PropertyDiagLoc, diag::err_atomic_property_nontrivial_assign_op) << property->getType(); Diag(FuncDecl->getLocStart(), diff --git a/test/SemaObjCXX/property-synthesis-error.mm b/test/SemaObjCXX/property-synthesis-error.mm index 1d93523b4c..b6ab85ccab 100644 --- a/test/SemaObjCXX/property-synthesis-error.mm +++ b/test/SemaObjCXX/property-synthesis-error.mm @@ -83,3 +83,24 @@ struct ConvertToIncomplete { operator IncompleteStruct&(); }; @implementation SynthIncompleteRef // expected-error {{cannot synthesize property 'x' with incomplete type 'IncompleteStruct'}} @synthesize y; // expected-error {{cannot synthesize property 'y' with incomplete type 'IncompleteStruct'}} @end + + +// Check error handling for instantiation during property synthesis. +template<typename T> class TemplateClass1 { + T *x; // expected-error {{'x' declared as a pointer to a reference of type 'int &'}} +}; +template<typename T> class TemplateClass2 { + TemplateClass2& operator=(TemplateClass1<T>); + TemplateClass2& operator=(TemplateClass2) { T(); } // expected-error {{reference to type 'int' requires an initializer}} \ + // expected-note 2 {{implicitly declared private here}} \ + // expected-note {{'operator=' declared here}} +}; +__attribute__((objc_root_class)) @interface InterfaceWithTemplateProperties +@property TemplateClass2<int&> intprop; +@property TemplateClass2<int&> &floatprop; +@end +@implementation InterfaceWithTemplateProperties // expected-error 2 {{'operator=' is a private member of 'TemplateClass2<int &>'}} \ + // expected-error {{atomic property of reference type 'TemplateClass2<int &> &' cannot have non-trivial assignment operator}} \ + // expected-note {{in instantiation of template class}} \ + // expected-note {{in instantiation of member function}} +@end |