Author: rjmccall Date: Wed Mar 2 18:10:03 2016 New Revision: 262551 URL: http://llvm.org/viewvc/llvm-project?rev=262551&view=rev Log: Improve some infrastructure for extended parameter infos and fix a bug with the instantiation of ns_consumed parameter attributes in ARC.
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/include/clang/Sema/AttributeList.h cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/AST/TypePrinter.cpp cfe/trunk/lib/Sema/SemaDeclAttr.cpp cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp cfe/trunk/lib/Sema/SemaType.cpp cfe/trunk/test/SemaCXX/cxx11-gnu-attrs.cpp cfe/trunk/test/SemaObjCXX/arc-nsconsumed-errors.mm cfe/trunk/test/SemaObjCXX/arc-templates.mm Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=262551&r1=262550&r2=262551&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Mar 2 18:10:03 2016 @@ -2934,6 +2934,9 @@ def warn_ns_attribute_wrong_return_type "%0 attribute only applies to %select{functions|methods|properties}1 that " "return %select{an Objective-C object|a pointer|a non-retainable pointer}2">, InGroup<IgnoredAttributes>; +def err_ns_attribute_wrong_parameter_type : Error< + "%0 attribute only applies to " + "%select{Objective-C object|pointer|pointer-to-CF-pointer}1 parameters">; def warn_ns_attribute_wrong_parameter_type : Warning< "%0 attribute only applies to " "%select{Objective-C object|pointer|pointer-to-CF-pointer}1 parameters">, Modified: cfe/trunk/include/clang/Sema/AttributeList.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/AttributeList.h?rev=262551&r1=262550&r2=262551&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/AttributeList.h (original) +++ cfe/trunk/include/clang/Sema/AttributeList.h Wed Mar 2 18:10:03 2016 @@ -94,9 +94,11 @@ private: SourceLocation ScopeLoc; SourceLocation EllipsisLoc; + unsigned AttrKind : 16; + /// The number of expression arguments this attribute has. /// The expressions themselves are stored after the object. - unsigned NumArgs : 15; + unsigned NumArgs : 16; /// Corresponds to the Syntax enum. unsigned SyntaxUsed : 3; @@ -122,7 +124,11 @@ private: /// True if this has a ParsedType unsigned HasParsedType : 1; - unsigned AttrKind : 8; + /// True if the processing cache is valid. + mutable unsigned HasProcessingCache : 1; + + /// A cached value. + mutable unsigned ProcessingCache : 8; /// \brief The location of the 'unavailable' keyword in an /// availability attribute. @@ -231,7 +237,8 @@ private: ScopeLoc(scopeLoc), EllipsisLoc(ellipsisLoc), NumArgs(numArgs), SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false), - HasParsedType(false), NextInPosition(nullptr), NextInPool(nullptr) { + HasParsedType(false), HasProcessingCache(false), + NextInPosition(nullptr), NextInPool(nullptr) { if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion)); AttrKind = getKind(getName(), getScopeName(), syntaxUsed); } @@ -249,8 +256,8 @@ private: ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false), IsAvailability(true), IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false), - UnavailableLoc(unavailable), MessageExpr(messageExpr), - NextInPosition(nullptr), NextInPool(nullptr) { + HasProcessingCache(false), UnavailableLoc(unavailable), + MessageExpr(messageExpr), NextInPosition(nullptr), NextInPool(nullptr) { ArgsUnion PVal(Parm); memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion)); new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced); @@ -271,7 +278,7 @@ private: ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(3), SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false), - NextInPosition(nullptr), NextInPool(nullptr) { + HasProcessingCache(false), NextInPosition(nullptr), NextInPool(nullptr) { ArgsVector Args; Args.push_back(Parm1); Args.push_back(Parm2); @@ -289,7 +296,7 @@ private: ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), IsTypeTagForDatatype(true), IsProperty(false), HasParsedType(false), - NextInPosition(nullptr), NextInPool(nullptr) { + HasProcessingCache(false), NextInPosition(nullptr), NextInPool(nullptr) { ArgsUnion PVal(ArgKind); memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion)); TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot(); @@ -307,7 +314,7 @@ private: ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(true), - NextInPosition(nullptr), NextInPool(nullptr) { + HasProcessingCache(false), NextInPosition(nullptr), NextInPool(nullptr){ new (&getTypeBuffer()) ParsedType(typeArg); AttrKind = getKind(getName(), getScopeName(), syntaxUsed); } @@ -321,7 +328,7 @@ private: ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(true), HasParsedType(false), - NextInPosition(nullptr), NextInPool(nullptr) { + HasProcessingCache(false), NextInPosition(nullptr), NextInPool(nullptr) { new (&getPropertyDataBuffer()) PropertyData(getterId, setterId); AttrKind = getKind(getName(), getScopeName(), syntaxUsed); } @@ -373,6 +380,16 @@ public: bool isInvalid() const { return Invalid; } void setInvalid(bool b = true) const { Invalid = b; } + bool hasProcessingCache() const { return HasProcessingCache; } + unsigned getProcessingCache() const { + assert(hasProcessingCache()); + return ProcessingCache; + } + void setProcessingCache(unsigned value) const { + ProcessingCache = value; + HasProcessingCache = true; + } + bool isUsedAsTypeAttr() const { return UsedAsTypeAttr; } void setUsedAsTypeAttr() { UsedAsTypeAttr = true; } Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=262551&r1=262550&r2=262551&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Wed Mar 2 18:10:03 2016 @@ -7786,6 +7786,10 @@ public: void AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name, unsigned SpellingListIndex, bool InInstantiation = false); + void AddNSConsumedAttr(SourceRange AttrRange, Decl *D, + unsigned SpellingListIndex, bool isNSConsumed, + bool isTemplateInstantiation); + //===--------------------------------------------------------------------===// // C++ Coroutines TS // Modified: cfe/trunk/lib/AST/TypePrinter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypePrinter.cpp?rev=262551&r1=262550&r2=262551&view=diff ============================================================================== --- cfe/trunk/lib/AST/TypePrinter.cpp (original) +++ cfe/trunk/lib/AST/TypePrinter.cpp Wed Mar 2 18:10:03 2016 @@ -641,6 +641,10 @@ void TypePrinter::printFunctionProtoAfte ParamPolicyRAII ParamPolicy(Policy); for (unsigned i = 0, e = T->getNumParams(); i != e; ++i) { if (i) OS << ", "; + + auto EPI = T->getExtParameterInfo(i); + if (EPI.isConsumed()) OS << "__attribute__((ns_consumed)) "; + print(T->getParamType(i), OS, StringRef()); } } Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=262551&r1=262550&r2=262551&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Wed Mar 2 18:10:03 2016 @@ -3777,6 +3777,11 @@ bool Sema::CheckCallingConvAttr(const At if (attr.isInvalid()) return true; + if (attr.hasProcessingCache()) { + CC = (CallingConv) attr.getProcessingCache(); + return false; + } + unsigned ReqArgs = attr.getKind() == AttributeList::AT_Pcs ? 1 : 0; if (!checkAttributeNumArgs(*this, attr, ReqArgs)) { attr.setInvalid(); @@ -3836,6 +3841,7 @@ bool Sema::CheckCallingConvAttr(const At CC = TI.getDefaultCallingConv(MT); } + attr.setProcessingCache((unsigned) CC); return false; } @@ -4030,31 +4036,45 @@ static bool isValidSubjectOfCFAttribute( } static void handleNSConsumedAttr(Sema &S, Decl *D, const AttributeList &Attr) { + S.AddNSConsumedAttr(Attr.getRange(), D, Attr.getAttributeSpellingListIndex(), + Attr.getKind() == AttributeList::AT_NSConsumed, + /*template instantiation*/ false); +} + +void Sema::AddNSConsumedAttr(SourceRange attrRange, Decl *D, + unsigned spellingIndex, bool isNSConsumed, + bool isTemplateInstantiation) { ParmVarDecl *param = cast<ParmVarDecl>(D); - bool typeOK, cf; + bool typeOK; - if (Attr.getKind() == AttributeList::AT_NSConsumed) { - typeOK = isValidSubjectOfNSAttribute(S, param->getType()); - cf = false; + if (isNSConsumed) { + typeOK = isValidSubjectOfNSAttribute(*this, param->getType()); } else { - typeOK = isValidSubjectOfCFAttribute(S, param->getType()); - cf = true; + typeOK = isValidSubjectOfCFAttribute(*this, param->getType()); } if (!typeOK) { - S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_parameter_type) - << Attr.getRange() << Attr.getName() << cf; + // These attributes are normally just advisory, but in ARC, ns_consumed + // is significant. Allow non-dependent code to contain inappropriate + // attributes even in ARC, but require template instantiations to be + // set up correctly. + Diag(D->getLocStart(), + (isTemplateInstantiation && isNSConsumed && + getLangOpts().ObjCAutoRefCount + ? diag::err_ns_attribute_wrong_parameter_type + : diag::warn_ns_attribute_wrong_parameter_type)) + << attrRange + << (isNSConsumed ? "ns_consumed" : "cf_consumed") + << (isNSConsumed ? /*objc pointers*/ 0 : /*cf pointers*/ 1); return; } - if (cf) - param->addAttr(::new (S.Context) - CFConsumedAttr(Attr.getRange(), S.Context, - Attr.getAttributeSpellingListIndex())); + if (isNSConsumed) + param->addAttr(::new (Context) + NSConsumedAttr(attrRange, Context, spellingIndex)); else - param->addAttr(::new (S.Context) - NSConsumedAttr(Attr.getRange(), S.Context, - Attr.getAttributeSpellingListIndex())); + param->addAttr(::new (Context) + CFConsumedAttr(attrRange, Context, spellingIndex)); } static void handleNSReturnsRetainedAttr(Sema &S, Decl *D, Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=262551&r1=262550&r2=262551&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Wed Mar 2 18:10:03 2016 @@ -286,6 +286,14 @@ void Sema::InstantiateAttrs(const MultiL } } + if (isa<NSConsumedAttr>(TmplAttr) || isa<CFConsumedAttr>(TmplAttr)) { + AddNSConsumedAttr(TmplAttr->getRange(), New, + TmplAttr->getSpellingListIndex(), + isa<NSConsumedAttr>(TmplAttr), + /*template instantiation*/ true); + continue; + } + assert(!TmplAttr->isPackExpansion()); if (TmplAttr->isLateParsed() && LateAttrs) { // Late parsed attributes must be instantiated and attached after the Modified: cfe/trunk/lib/Sema/SemaType.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=262551&r1=262550&r2=262551&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaType.cpp (original) +++ cfe/trunk/lib/Sema/SemaType.cpp Wed Mar 2 18:10:03 2016 @@ -100,9 +100,8 @@ static void diagnoseBadTypeAttribute(Sem case AttributeList::AT_ObjCGC: \ case AttributeList::AT_ObjCOwnership -// Function type attributes. -#define FUNCTION_TYPE_ATTRS_CASELIST \ - case AttributeList::AT_NoReturn: \ +// Calling convention attributes. +#define CALLING_CONV_ATTRS_CASELIST \ case AttributeList::AT_CDecl: \ case AttributeList::AT_FastCall: \ case AttributeList::AT_StdCall: \ @@ -111,10 +110,15 @@ static void diagnoseBadTypeAttribute(Sem case AttributeList::AT_VectorCall: \ case AttributeList::AT_MSABI: \ case AttributeList::AT_SysVABI: \ - case AttributeList::AT_Regparm: \ case AttributeList::AT_Pcs: \ case AttributeList::AT_IntelOclBicc +// Function type attributes. +#define FUNCTION_TYPE_ATTRS_CASELIST \ + case AttributeList::AT_NoReturn: \ + case AttributeList::AT_Regparm: \ + CALLING_CONV_ATTRS_CASELIST + // Microsoft-specific type qualifiers. #define MS_TYPE_ATTRS_CASELIST \ case AttributeList::AT_Ptr32: \ @@ -2957,6 +2961,26 @@ getCCForDeclaratorChunk(Sema &S, Declara unsigned ChunkIndex) { assert(D.getTypeObject(ChunkIndex).Kind == DeclaratorChunk::Function); + // Check for an explicit CC attribute. + for (auto Attr = FTI.AttrList; Attr; Attr = Attr->getNext()) { + switch (Attr->getKind()) { + CALLING_CONV_ATTRS_CASELIST: { + // Ignore attributes that don't validate or can't apply to the + // function type. We'll diagnose the failure to apply them in + // handleFunctionTypeAttr. + CallingConv CC; + if (!S.CheckCallingConvAttr(*Attr, CC) && + (!FTI.isVariadic || supportsVariadicCall(CC))) { + return CC; + } + break; + } + + default: + break; + } + } + bool IsCXXInstanceMethod = false; if (S.getLangOpts().CPlusPlus) { @@ -5986,9 +6010,14 @@ static bool handleFunctionTypeAttr(TypeP // Modify the CC from the wrapped function type, wrap it all back, and then // wrap the whole thing in an AttributedType as written. The modified type // might have a different CC if we ignored the attribute. - FunctionType::ExtInfo EI = unwrapped.get()->getExtInfo().withCallingConv(CC); - QualType Equivalent = + QualType Equivalent; + if (CCOld == CC) { + Equivalent = type; + } else { + auto EI = unwrapped.get()->getExtInfo().withCallingConv(CC); + Equivalent = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI)); + } type = S.Context.getAttributedType(CCAttrKind, type, Equivalent); return true; } Modified: cfe/trunk/test/SemaCXX/cxx11-gnu-attrs.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx11-gnu-attrs.cpp?rev=262551&r1=262550&r2=262551&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/cxx11-gnu-attrs.cpp (original) +++ cfe/trunk/test/SemaCXX/cxx11-gnu-attrs.cpp Wed Mar 2 18:10:03 2016 @@ -19,6 +19,7 @@ int *[[gnu::unused]] attr_on_ptr; [[gnu::fastcall]] void pr17424_4() [[gnu::stdcall]]; // expected-warning@-1 {{calling convention 'fastcall' ignored for this target}} // expected-warning@-2 {{attribute 'stdcall' ignored, because it cannot be applied to a type}} +// expected-warning@-3 {{calling convention 'stdcall' ignored for this target}} void pr17424_5 [[gnu::fastcall]](); // expected-warning@-1 {{calling convention 'fastcall' ignored for this target}} Modified: cfe/trunk/test/SemaObjCXX/arc-nsconsumed-errors.mm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/arc-nsconsumed-errors.mm?rev=262551&r1=262550&r2=262551&view=diff ============================================================================== --- cfe/trunk/test/SemaObjCXX/arc-nsconsumed-errors.mm (original) +++ cfe/trunk/test/SemaObjCXX/arc-nsconsumed-errors.mm Wed Mar 2 18:10:03 2016 @@ -29,9 +29,9 @@ void releaser(__attribute__((ns_consumed releaser_t r2 = releaser; // no-warning template <typename T> -void templateFunction(T) { } // expected-note {{candidate template ignored: could not match 'void (__strong id)' against 'void (id)'}} \ +void templateFunction(T) { } // expected-note {{candidate template ignored: could not match 'void (__strong id)' against 'void (__attribute__((ns_consumed)) id)'}} \ // expected-note {{candidate template ignored: failed template argument deduction}} -releaser_t r3 = templateFunction<id>; // expected-error {{address of overloaded function 'templateFunction' does not match required type 'void (id)'}} +releaser_t r3 = templateFunction<id>; // expected-error {{address of overloaded function 'templateFunction' does not match required type 'void (__attribute__((ns_consumed)) id)'}} template <typename T> void templateReleaser(__attribute__((ns_consumed)) T) { } // expected-note 2{{candidate template ignored: failed template argument deduction}} Modified: cfe/trunk/test/SemaObjCXX/arc-templates.mm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/arc-templates.mm?rev=262551&r1=262550&r2=262551&view=diff ============================================================================== --- cfe/trunk/test/SemaObjCXX/arc-templates.mm (original) +++ cfe/trunk/test/SemaObjCXX/arc-templates.mm Wed Mar 2 18:10:03 2016 @@ -442,3 +442,11 @@ namespace produced_nested { take_no(produces<4>::fn); // expected-error {{no matching function}} } } + +namespace instantiate_consumed { + template <class T> void take(CONSUMED T t) {} // expected-note {{candidate template ignored: substitution failure [with T = int]: ns_consumed attribute only applies to Objective-C object parameters}} + void test() { + take((id) 0); + take((int) 0); // expected-error {{no matching function for call to 'take'}} + } +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits