From: Argyrios Kyrtzidis Date: Mon, 14 Nov 2011 04:52:29 +0000 (+0000) Subject: [PCH] Do not crash if a class extension in a chained PCH introduces/redeclares a... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c80553efdc269dabd4ed0c3210555f45729ab5dd;p=clang [PCH] Do not crash if a class extension in a chained PCH introduces/redeclares a property. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@144520 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h index 03b658cd47..86a93153b9 100644 --- a/include/clang/AST/ASTMutationListener.h +++ b/include/clang/AST/ASTMutationListener.h @@ -25,6 +25,7 @@ namespace clang { class ObjCCategoryDecl; class ObjCInterfaceDecl; class ObjCContainerDecl; + class ObjCPropertyDecl; /// \brief An abstract interface that should be implemented by listeners /// that want to be notified when an AST entity gets modified after its @@ -65,6 +66,18 @@ public: /// \brief A objc interface or protocol forward reference was completed. virtual void CompletedObjCForwardRef(const ObjCContainerDecl *D) {} + /// \brief A objc class extension redeclared or introduced a property. + /// + /// \param Prop the property in the class extension + /// + /// \param OrigProp the property from the original interface that was declared + /// or null if the property was introduced. + /// + /// \param ClassExt the class extension. + virtual void AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop, + const ObjCPropertyDecl *OrigProp, + const ObjCCategoryDecl *ClassExt) {} + /// \brief The attributes list of a declaration was updated. virtual void UpdatedAttributeList(const Decl *D) {} }; diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index 3c8ef2b1ab..5d97c1815b 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -661,6 +661,9 @@ public: virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, const ObjCInterfaceDecl *IFD); virtual void CompletedObjCForwardRef(const ObjCContainerDecl *D); + virtual void AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop, + const ObjCPropertyDecl *OrigProp, + const ObjCCategoryDecl *ClassExt); virtual void UpdatedAttributeList(const Decl *D); }; diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index 4933f001c4..90d2d93431 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -17,6 +17,7 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/ASTMutationListener.h" #include "llvm/ADT/DenseSet.h" using namespace clang; @@ -271,6 +272,8 @@ Sema::HandlePropertyInClassExtension(Scope *S, // Make sure setter/getters are declared here. ProcessPropertyDecl(PDecl, CCPrimary, /* redeclaredProperty = */ 0, /* lexicalDC = */ CDecl); + if (ASTMutationListener *L = Context.getASTMutationListener()) + L->AddedObjCPropertyInClassExtension(PDecl, /*OrigProp=*/0, CDecl); return PDecl; } if (PIDecl->getType().getCanonicalType() @@ -343,6 +346,8 @@ Sema::HandlePropertyInClassExtension(Scope *S, *isOverridingProperty = true; // Make sure setter decl is synthesized, and added to primary class's list. ProcessPropertyDecl(PIDecl, CCPrimary, PDecl, CDecl); + if (ASTMutationListener *L = Context.getASTMutationListener()) + L->AddedObjCPropertyInClassExtension(PDecl, PIDecl, CDecl); return 0; } diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 8f79fa4c49..4fa3cf8756 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -4130,6 +4130,20 @@ void ASTWriter::CompletedObjCForwardRef(const ObjCContainerDecl *D) { RewriteDecl(D); } +void ASTWriter::AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop, + const ObjCPropertyDecl *OrigProp, + const ObjCCategoryDecl *ClassExt) { + const ObjCInterfaceDecl *D = ClassExt->getClassInterface(); + if (!D) + return; + + assert(!WritingAST && "Already writing the AST!"); + if (!D->isFromASTFile()) + return; // Declaration not imported from PCH. + + RewriteDecl(D); +} + void ASTWriter::UpdatedAttributeList(const Decl *D) { assert(!WritingAST && "Already writing the AST!"); if (!D->isFromASTFile()) diff --git a/test/PCH/chain-categories2.m b/test/PCH/chain-categories2.m index dcff3d4af0..6b9708566c 100644 --- a/test/PCH/chain-categories2.m +++ b/test/PCH/chain-categories2.m @@ -13,6 +13,10 @@ @class I; +@interface I2 +@property (readonly) id prop1; +@end + //===----------------------------------------------------------------------===// #elif !defined(HEADER2) #define HEADER2 @@ -32,6 +36,11 @@ @interface I(Cat2) @end +@interface I2() +@property (readwrite,assign) id prop1; +@property (copy) id prop2; +@end + //===----------------------------------------------------------------------===// #else //===----------------------------------------------------------------------===// @@ -40,5 +49,9 @@ void f(I* i) { [i meth]; // expected-warning {{not found}} } +@implementation I2 +@synthesize prop1, prop2; +@end + //===----------------------------------------------------------------------===// #endif