From: Fariborz Jahanian Date: Tue, 9 Feb 2010 19:31:38 +0000 (+0000) Subject: Implement synthesizing properties by default. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=412e798941ca64e2e6b084323915fa9aa5f6bdf3;p=clang Implement synthesizing properties by default. This is a non-fragile-abi feature only. Since it breaks existing code, it is currently placed under -fobjc-nonfragile-abi2 option for test purposes only until further notice. WIP. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95685 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index 01104fc543..aa91d46350 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -109,6 +109,10 @@ def warn_pch_objective_c2 : Error< def warn_pch_nonfragile_abi : Error< "PCH file was compiled with the %select{32-bit|non-fragile}0 Objective-C " "ABI but the %select{32-bit|non-fragile}1 Objective-C ABI is selected">; +def warn_pch_nonfragile_abi2 : Error< + "PCH file was compiled with the %select{32-bit|enhanced non-fragile}0 " + "Objective-C ABI but the %select{32-bit|enhanced non-fragile}1 " + "Objective-C ABI is selected">; def warn_pch_extensions : Error< "extensions were %select{enabled|disabled}0 in PCH file but are " "currently %select{enabled|disabled}1">; diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index 2abf9ef7a0..d97e61cc16 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -40,6 +40,7 @@ public: unsigned ObjC1 : 1; // Objective-C 1 support enabled. unsigned ObjC2 : 1; // Objective-C 2 support enabled. unsigned ObjCNonFragileABI : 1; // Objective-C modern abi enabled + unsigned ObjCNonFragileABI2 : 1; // Objective-C enhanced modern abi enabled unsigned PascalStrings : 1; // Allow Pascal strings unsigned WritableStrings : 1; // Allow writable strings @@ -124,7 +125,7 @@ public: Trigraphs = BCPLComment = Bool = DollarIdents = AsmPreprocessor = 0; GNUMode = ImplicitInt = Digraphs = 0; HexFloats = 0; - GC = ObjC1 = ObjC2 = ObjCNonFragileABI = 0; + GC = ObjC1 = ObjC2 = ObjCNonFragileABI = ObjCNonFragileABI2 = 0; C99 = Microsoft = CPlusPlus = CPlusPlus0x = 0; CXXOperatorNames = PascalStrings = WritableStrings = 0; Exceptions = Freestanding = NoBuiltin = 0; diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index f0db6e7caf..5f1983d4cb 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -360,6 +360,8 @@ def print_ivar_layout : Flag<"-print-ivar-layout">, HelpText<"Enable Objective-C Ivar layout bitmap print trace">; def fobjc_nonfragile_abi : Flag<"-fobjc-nonfragile-abi">, HelpText<"enable objective-c's nonfragile abi">; +def fobjc_nonfragile_abi2 : Flag<"-fobjc-nonfragile-abi2">, + HelpText<"enable objective-c's enhanced nonfragile abi">; def ftrapv : Flag<"-ftrapv">, HelpText<"Trap on integer overflow">; def pic_level : Separate<"-pic-level">, diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 767123b14b..e42e2cc9c9 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -323,6 +323,7 @@ def fobjc_gc : Flag<"-fobjc-gc">, Group; def fobjc_legacy_dispatch : Flag<"-fobjc-legacy-dispatch">, Group; def fobjc_new_property : Flag<"-fobjc-new-property">, Group; def fobjc_nonfragile_abi : Flag<"-fobjc-nonfragile-abi">, Group; +def fobjc_nonfragile_abi2 : Flag<"-fobjc-nonfragile-abi2">, Group; def fobjc_sender_dependent_dispatch : Flag<"-fobjc-sender-dependent-dispatch">, Group; def fobjc : Flag<"-fobjc">, Group; def fomit_frame_pointer : Flag<"-fomit-frame-pointer">, Group; diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 006f3c095c..35cfee85fc 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -459,6 +459,8 @@ static void LangOptsToArgs(const LangOptions &Opts, Res.push_back("-fms-extensions"); if (Opts.ObjCNonFragileABI) Res.push_back("-fobjc-nonfragile-abi"); + if (Opts.ObjCNonFragileABI2) + Res.push_back("-fobjc-nonfragile-abi2"); // NoInline is implicit. if (!Opts.CXXOperatorNames) Res.push_back("-fno-operator-names"); @@ -1181,6 +1183,9 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.ObjCConstantStringClass = getLastArgValue(Args, OPT_fconstant_string_class); Opts.ObjCNonFragileABI = Args.hasArg(OPT_fobjc_nonfragile_abi); + Opts.ObjCNonFragileABI2 = Args.hasArg(OPT_fobjc_nonfragile_abi2); + if (Opts.ObjCNonFragileABI2) + Opts.ObjCNonFragileABI = true; Opts.CatchUndefined = Args.hasArg(OPT_fcatch_undefined_behavior); Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls); Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags); diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 1ed5260a88..9ab3b7a0a2 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -72,6 +72,7 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) { PARSE_LANGOPT_IMPORTANT(ObjC1, diag::warn_pch_objective_c); PARSE_LANGOPT_IMPORTANT(ObjC2, diag::warn_pch_objective_c2); PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI, diag::warn_pch_nonfragile_abi); + PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI2, diag::warn_pch_nonfragile_abi2); PARSE_LANGOPT_BENIGN(PascalStrings); PARSE_LANGOPT_BENIGN(WritableStrings); PARSE_LANGOPT_IMPORTANT(LaxVectorConversions, @@ -1740,6 +1741,7 @@ bool PCHReader::ParseLanguageOptions( PARSE_LANGOPT(ObjC1); PARSE_LANGOPT(ObjC2); PARSE_LANGOPT(ObjCNonFragileABI); + PARSE_LANGOPT(ObjCNonFragileABI2); PARSE_LANGOPT(PascalStrings); PARSE_LANGOPT(WritableStrings); PARSE_LANGOPT(LaxVectorConversions); diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 5085cf43d0..45d9b1bace 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -748,7 +748,10 @@ void PCHWriter::WriteLanguageOptions(const LangOptions &LangOpts) { Record.push_back(LangOpts.ObjC1); // Objective-C 1 support enabled. Record.push_back(LangOpts.ObjC2); // Objective-C 2 support enabled. - Record.push_back(LangOpts.ObjCNonFragileABI); // Objective-C modern abi enabled + Record.push_back(LangOpts.ObjCNonFragileABI); // Objective-C + // modern abi enabled. + Record.push_back(LangOpts.ObjCNonFragileABI2); // Objective-C enhanced + // modern abi enabled. Record.push_back(LangOpts.PascalStrings); // Allow Pascal strings Record.push_back(LangOpts.WritableStrings); // Allow writable strings diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index ead808fdeb..bf6888762f 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1358,6 +1358,11 @@ public: void CollectImmediateProperties(ObjCContainerDecl *CDecl, llvm::DenseMap& PropMap); + /// LookupPropertyDecl - Looks up a property in the current class and all + /// its protocols. + ObjCPropertyDecl *LookupPropertyDecl(const ObjCContainerDecl *CDecl, + IdentifierInfo *II); + /// AtomicPropertySetterGetterRules - This routine enforces the rule (via /// warning) when atomic property has one but not the other user-declared /// setter or getter. diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 1b07d19882..c0e8219f67 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -1127,6 +1127,46 @@ void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl, } } +/// LookupPropertyDecl - Looks up a property in the current class and all +/// its protocols. +ObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl, + IdentifierInfo *II) { + if (const ObjCInterfaceDecl *IDecl = + dyn_cast(CDecl)) { + for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(), + E = IDecl->prop_end(); P != E; ++P) { + ObjCPropertyDecl *Prop = (*P); + if (Prop->getIdentifier() == II) + return Prop; + } + // scan through class's protocols. + for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(), + E = IDecl->protocol_end(); PI != E; ++PI) { + ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II); + if (Prop) + return Prop; + } + } + else if (const ObjCProtocolDecl *PDecl = + dyn_cast(CDecl)) { + for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), + E = PDecl->prop_end(); P != E; ++P) { + ObjCPropertyDecl *Prop = (*P); + if (Prop->getIdentifier() == II) + return Prop; + } + // scan through protocol's protocols. + for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), + E = PDecl->protocol_end(); PI != E; ++PI) { + ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II); + if (Prop) + return Prop; + } + } + return 0; +} + + void Sema::DiagnoseUnimplementedProperties(ObjCImplDecl* IMPDecl, ObjCContainerDecl *CDecl, const llvm::DenseSet& InsMap) { @@ -1149,7 +1189,14 @@ void Sema::DiagnoseUnimplementedProperties(ObjCImplDecl* IMPDecl, Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional || PropImplMap.count(Prop)) continue; - + if (LangOpts.ObjCNonFragileABI2) { + ActOnPropertyImplDecl(IMPDecl->getLocation(), + SourceLocation(), + true, DeclPtrTy::make(IMPDecl), + Prop->getIdentifier(), + Prop->getIdentifier()); + continue; + } if (!InsMap.count(Prop->getGetterName())) { Diag(Prop->getLocation(), isa(CDecl) ? diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index abb4e786d6..0da57330ee 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1271,9 +1271,9 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, else LookForIvars = (Lookup.isSingleResult() && Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod()); - + ObjCInterfaceDecl *IFace = 0; if (LookForIvars) { - ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface(); + IFace = getCurMethodDecl()->getClassInterface(); ObjCInterfaceDecl *ClassDeclared; if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) { // Diagnose using an ivar in a class method. @@ -1342,6 +1342,24 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, } } } + if (LangOpts.ObjCNonFragileABI2 && LookForIvars && Lookup.empty()) { + // Find property name matching variable name. + ObjCPropertyDecl *Prop = LookupPropertyDecl(IFace, II); + if (Prop && !Prop->isInvalidDecl()) { + DeclContext *EnclosingContext = cast_or_null(IFace); + QualType PropType = Context.getCanonicalType(Prop->getType()); + assert(EnclosingContext && + "null DeclContext for synthesized ivar - LookupInObjCMethod"); + ObjCIvarDecl *Ivar = ObjCIvarDecl::Create(Context, EnclosingContext, + Prop->getLocation(), + II, PropType, /*Dinfo=*/0, + ObjCIvarDecl::Public, + (Expr *)0); + Ivar->setLexicalDeclContext(IFace); + IFace->addDecl(Ivar); + return LookupInObjCMethod(Lookup, S, II, AllowBuiltinCreation); + } + } // Sentinel value saying that we didn't do anything special. return Owned((Expr*) 0); }