diff options
Diffstat (limited to 'clang/lib/Sema/SemaDeclAttr.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 842 |
1 files changed, 477 insertions, 365 deletions
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 30d08b3d4ac0..bb4ce8d4962e 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -23,6 +23,7 @@ #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Type.h" #include "clang/Basic/CharInfo.h" +#include "clang/Basic/DarwinSDKInfo.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetBuiltins.h" @@ -40,6 +41,8 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/IR/Assumptions.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/Support/Error.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" @@ -153,7 +156,8 @@ static bool isInstanceMethod(const Decl *D) { return false; } -static inline bool isNSStringType(QualType T, ASTContext &Ctx) { +static inline bool isNSStringType(QualType T, ASTContext &Ctx, + bool AllowNSAttributedString = false) { const auto *PT = T->getAs<ObjCObjectPointerType>(); if (!PT) return false; @@ -164,6 +168,9 @@ static inline bool isNSStringType(QualType T, ASTContext &Ctx) { IdentifierInfo* ClsName = Cls->getIdentifier(); + if (AllowNSAttributedString && + ClsName == &Ctx.Idents.get("NSAttributedString")) + return true; // FIXME: Should we walk the chain of classes? return ClsName == &Ctx.Idents.get("NSString") || ClsName == &Ctx.Idents.get("NSMutableString"); @@ -190,44 +197,6 @@ static unsigned getNumAttributeArgs(const ParsedAttr &AL) { return AL.getNumArgs() + AL.hasParsedType(); } -template <typename Compare> -static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL, - unsigned Num, unsigned Diag, - Compare Comp) { - if (Comp(getNumAttributeArgs(AL), Num)) { - S.Diag(AL.getLoc(), Diag) << AL << Num; - return false; - } - - return true; -} - -/// Check if the attribute has exactly as many args as Num. May -/// output an error. -static bool checkAttributeNumArgs(Sema &S, const ParsedAttr &AL, unsigned Num) { - return checkAttributeNumArgsImpl(S, AL, Num, - diag::err_attribute_wrong_number_arguments, - std::not_equal_to<unsigned>()); -} - -/// Check if the attribute has at least as many args as Num. May -/// output an error. -static bool checkAttributeAtLeastNumArgs(Sema &S, const ParsedAttr &AL, - unsigned Num) { - return checkAttributeNumArgsImpl(S, AL, Num, - diag::err_attribute_too_few_arguments, - std::less<unsigned>()); -} - -/// Check if the attribute has at most as many args as Num. May -/// output an error. -static bool checkAttributeAtMostNumArgs(Sema &S, const ParsedAttr &AL, - unsigned Num) { - return checkAttributeNumArgsImpl(S, AL, Num, - diag::err_attribute_too_many_arguments, - std::greater<unsigned>()); -} - /// A helper function to provide Attribute Location for the Attr types /// AND the ParsedAttr. template <typename AttrInfo> @@ -261,7 +230,7 @@ static bool checkUInt32Argument(Sema &S, const AttrInfo &AI, const Expr *Expr, if (!I->isIntN(32)) { S.Diag(Expr->getExprLoc(), diag::err_ice_too_large) - << I->toString(10, false) << 32 << /* Unsigned */ 1; + << toString(*I, 10, false) << 32 << /* Unsigned */ 1; return false; } @@ -289,7 +258,7 @@ static bool checkPositiveIntArgument(Sema &S, const AttrInfo &AI, const Expr *Ex llvm::APSInt I(32); // for toString I = UVal; S.Diag(Expr->getExprLoc(), diag::err_ice_too_large) - << I.toString(10, false) << 32 << /* Unsigned */ 0; + << toString(I, 10, false) << 32 << /* Unsigned */ 0; return false; } @@ -423,10 +392,10 @@ appendDiagnostics(const Sema::SemaDiagnosticBuilder &Bldr, T &&ExtraArg, std::forward<DiagnosticArgs>(ExtraArgs)...); } -/// Add an attribute {@code AttrType} to declaration {@code D}, provided that -/// {@code PassesCheck} is true. -/// Otherwise, emit diagnostic {@code DiagID}, passing in all parameters -/// specified in {@code ExtraArgs}. +/// Add an attribute @c AttrType to declaration @c D, provided that +/// @c PassesCheck is true. +/// Otherwise, emit diagnostic @c DiagID, passing in all parameters +/// specified in @c ExtraArgs. template <typename AttrType, typename... DiagnosticArgs> static void handleSimpleAttributeOrDiagnose(Sema &S, Decl *D, const AttributeCommonInfo &CI, @@ -440,24 +409,6 @@ static void handleSimpleAttributeOrDiagnose(Sema &S, Decl *D, handleSimpleAttribute<AttrType>(S, D, CI); } -template <typename AttrType> -static void handleSimpleAttributeWithExclusions(Sema &S, Decl *D, - const ParsedAttr &AL) { - handleSimpleAttribute<AttrType>(S, D, AL); -} - -/// Applies the given attribute to the Decl so long as the Decl doesn't -/// already have one of the given incompatible attributes. -template <typename AttrType, typename IncompatibleAttrType, - typename... IncompatibleAttrTypes> -static void handleSimpleAttributeWithExclusions(Sema &S, Decl *D, - const ParsedAttr &AL) { - if (checkAttrMutualExclusion<IncompatibleAttrType>(S, D, AL)) - return; - handleSimpleAttributeWithExclusions<AttrType, IncompatibleAttrTypes...>(S, D, - AL); -} - /// Check if the passed-in expression is of type int or bool. static bool isIntOrBool(Expr *Exp) { QualType QT = Exp->getType(); @@ -546,16 +497,9 @@ static bool checkRecordDeclForAttr(const RecordDecl *RD) { // Else check if any base classes have the attribute. if (const auto *CRD = dyn_cast<CXXRecordDecl>(RD)) { - CXXBasePaths BPaths(false, false); - if (CRD->lookupInBases( - [](const CXXBaseSpecifier *BS, CXXBasePath &) { - const auto &Ty = *BS->getType(); - // If it's type-dependent, we assume it could have the attribute. - if (Ty.isDependentType()) - return true; - return Ty.castAs<RecordType>()->getDecl()->hasAttr<AttrType>(); - }, - BPaths, true)) + if (!CRD->forallBases([](const CXXRecordDecl *Base) { + return !Base->hasAttr<AttrType>(); + })) return true; } return false; @@ -770,7 +714,7 @@ static void handlePtGuardedByAttr(Sema &S, Decl *D, const ParsedAttr &AL) { static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL, SmallVectorImpl<Expr *> &Args) { - if (!checkAttributeAtLeastNumArgs(S, AL, 1)) + if (!AL.checkAtLeastNumArgs(S, 1)) return false; // Check that this attribute only applies to lockable types. @@ -846,32 +790,33 @@ static void handleAssertExclusiveLockAttr(Sema &S, Decl *D, /// /// AttrArgNo is used to actually retrieve the argument, so it's base-0. template <typename AttrInfo> -static bool checkParamIsIntegerType(Sema &S, const FunctionDecl *FD, - const AttrInfo &AI, unsigned AttrArgNo) { +static bool checkParamIsIntegerType(Sema &S, const Decl *D, const AttrInfo &AI, + unsigned AttrArgNo) { assert(AI.isArgExpr(AttrArgNo) && "Expected expression argument"); Expr *AttrArg = AI.getArgAsExpr(AttrArgNo); ParamIdx Idx; - if (!checkFunctionOrMethodParameterIndex(S, FD, AI, AttrArgNo + 1, AttrArg, + if (!checkFunctionOrMethodParameterIndex(S, D, AI, AttrArgNo + 1, AttrArg, Idx)) return false; - const ParmVarDecl *Param = FD->getParamDecl(Idx.getASTIndex()); - if (!Param->getType()->isIntegerType() && !Param->getType()->isCharType()) { + QualType ParamTy = getFunctionOrMethodParamType(D, Idx.getASTIndex()); + if (!ParamTy->isIntegerType() && !ParamTy->isCharType()) { SourceLocation SrcLoc = AttrArg->getBeginLoc(); S.Diag(SrcLoc, diag::err_attribute_integers_only) - << AI << Param->getSourceRange(); + << AI << getFunctionOrMethodParamRange(D, Idx.getASTIndex()); return false; } return true; } static void handleAllocSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (!checkAttributeAtLeastNumArgs(S, AL, 1) || - !checkAttributeAtMostNumArgs(S, AL, 2)) + if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 2)) return; - const auto *FD = cast<FunctionDecl>(D); - if (!FD->getReturnType()->isPointerType()) { + assert(isFunctionOrMethod(D) && hasFunctionProto(D)); + + QualType RetTy = getFunctionOrMethodResultType(D); + if (!RetTy->isPointerType()) { S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only) << AL; return; } @@ -881,7 +826,7 @@ static void handleAllocSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // Parameter indices are 1-indexed, hence Index=1 if (!checkPositiveIntArgument(S, AL, SizeExpr, SizeArgNoVal, /*Idx=*/1)) return; - if (!checkParamIsIntegerType(S, FD, AL, /*AttrArgNo=*/0)) + if (!checkParamIsIntegerType(S, D, AL, /*AttrArgNo=*/0)) return; ParamIdx SizeArgNo(SizeArgNoVal, D); @@ -892,7 +837,7 @@ static void handleAllocSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // Parameter indices are 1-based, hence Index=2 if (!checkPositiveIntArgument(S, AL, NumberExpr, Val, /*Idx=*/2)) return; - if (!checkParamIsIntegerType(S, FD, AL, /*AttrArgNo=*/1)) + if (!checkParamIsIntegerType(S, D, AL, /*AttrArgNo=*/1)) return; NumberArgNo = ParamIdx(Val, D); } @@ -903,7 +848,7 @@ static void handleAllocSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { static bool checkTryLockFunAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL, SmallVectorImpl<Expr *> &Args) { - if (!checkAttributeAtLeastNumArgs(S, AL, 1)) + if (!AL.checkAtLeastNumArgs(S, 1)) return false; if (!isIntOrBool(AL.getArgAsExpr(0))) { @@ -950,7 +895,7 @@ static void handleLockReturnedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } static void handleLocksExcludedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (!checkAttributeAtLeastNumArgs(S, AL, 1)) + if (!AL.checkAtLeastNumArgs(S, 1)) return; // check that all arguments are lockable objects @@ -1192,7 +1137,7 @@ static bool checkForConsumableClass(Sema &S, const CXXMethodDecl *MD, } static void handleCallableWhenAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (!checkAttributeAtLeastNumArgs(S, AL, 1)) + if (!AL.checkAtLeastNumArgs(S, 1)) return; if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), AL)) @@ -1991,6 +1936,12 @@ static void handleTLSModelAttr(Sema &S, Decl *D, const ParsedAttr &AL) { return; } + if (S.Context.getTargetInfo().getTriple().isOSAIX() && + Model != "global-dynamic") { + S.Diag(LiteralLoc, diag::err_aix_attr_unsupported_tls_model) << Model; + return; + } + D->addAttr(::new (S.Context) TLSModelAttr(S.Context, AL, Model)); } @@ -2015,7 +1966,7 @@ static void handleCPUSpecificAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } } - if (!checkAttributeAtLeastNumArgs(S, AL, 1)) + if (!AL.checkAtLeastNumArgs(S, 1)) return; SmallVector<IdentifierInfo *, 8> CPUs; @@ -2062,8 +2013,7 @@ static void handleCommonAttr(Sema &S, Decl *D, const ParsedAttr &AL) { return; } - if (CommonAttr *CA = S.mergeCommonAttr(D, AL)) - D->addAttr(CA); + D->addAttr(::new (S.Context) CommonAttr(S.Context, AL)); } static void handleCmseNSEntryAttr(Sema &S, Decl *D, const ParsedAttr &AL) { @@ -2082,9 +2032,6 @@ static void handleCmseNSEntryAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } static void handleNakedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (checkAttrMutualExclusion<DisableTailCallsAttr>(S, D, AL)) - return; - if (AL.isDeclspecAttribute()) { const auto &Triple = S.getASTContext().getTargetInfo().getTriple(); const auto &Arch = Triple.getArch(); @@ -2119,7 +2066,7 @@ static void handleNoCfCheckAttr(Sema &S, Decl *D, const ParsedAttr &Attrs) { } bool Sema::CheckAttrNoArgs(const ParsedAttr &Attrs) { - if (!checkAttributeNumArgs(*this, Attrs, 0)) { + if (!Attrs.checkExactlyNumArgs(*this, 0)) { Attrs.setInvalid(); return true; } @@ -2147,7 +2094,7 @@ static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &AL) { ValueDecl *VD = dyn_cast<ValueDecl>(D); if (!VD || (!VD->getType()->isBlockPointerType() && !VD->getType()->isFunctionPointerType())) { - S.Diag(AL.getLoc(), AL.isCXX11Attribute() + S.Diag(AL.getLoc(), AL.isStandardAttributeSyntax() ? diag::err_attribute_wrong_decl_type : diag::warn_attribute_wrong_decl_type) << AL << ExpectedFunctionMethodOrBlock; @@ -2354,6 +2301,7 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr( case AMK_Override: case AMK_ProtocolImplementation: + case AMK_OptionalProtocolImplementation: OverrideOrImpl = true; break; } @@ -2422,6 +2370,14 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr( diag::warn_mismatched_availability_override_unavail) << AvailabilityAttr::getPrettyPlatformName(Platform->getName()) << (AMK == AMK_Override); + } else if (Which != 1 && AMK == AMK_OptionalProtocolImplementation) { + // Allow different 'introduced' / 'obsoleted' availability versions + // on a method that implements an optional protocol requirement. It + // makes less sense to allow this for 'deprecated' as the user can't + // see if the method is 'deprecated' as 'respondsToSelector' will + // still return true when the method is deprecated. + ++i; + continue; } else { Diag(OldAA->getLocation(), diag::warn_mismatched_availability_override) @@ -2491,7 +2447,14 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr( } static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (!checkAttributeNumArgs(S, AL, 1)) + if (isa<UsingDecl, UnresolvedUsingTypenameDecl, UnresolvedUsingValueDecl>( + D)) { + S.Diag(AL.getRange().getBegin(), diag::warn_deprecated_ignored_on_using) + << AL; + return; + } + + if (!AL.checkExactlyNumArgs(S, 1)) return; IdentifierLoc *Platform = AL.getArgAsIdent(0); @@ -2594,15 +2557,90 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (NewAttr) D->addAttr(NewAttr); } + } else if (S.Context.getTargetInfo().getTriple().getOS() == + llvm::Triple::IOS && + S.Context.getTargetInfo().getTriple().isMacCatalystEnvironment()) { + auto GetSDKInfo = [&]() { + return S.getDarwinSDKInfoForAvailabilityChecking(AL.getRange().getBegin(), + "macOS"); + }; + + // Transcribe "ios" to "maccatalyst" (and add a new attribute). + IdentifierInfo *NewII = nullptr; + if (II->getName() == "ios") + NewII = &S.Context.Idents.get("maccatalyst"); + else if (II->getName() == "ios_app_extension") + NewII = &S.Context.Idents.get("maccatalyst_app_extension"); + if (NewII) { + auto MinMacCatalystVersion = [](const VersionTuple &V) { + if (V.empty()) + return V; + if (V.getMajor() < 13 || + (V.getMajor() == 13 && V.getMinor() && *V.getMinor() < 1)) + return VersionTuple(13, 1); // The min Mac Catalyst version is 13.1. + return V; + }; + AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr( + ND, AL.getRange(), NewII, true /*Implicit*/, + MinMacCatalystVersion(Introduced.Version), + MinMacCatalystVersion(Deprecated.Version), + MinMacCatalystVersion(Obsoleted.Version), IsUnavailable, Str, + IsStrict, Replacement, Sema::AMK_None, + PriorityModifier + Sema::AP_InferredFromOtherPlatform); + if (NewAttr) + D->addAttr(NewAttr); + } else if (II->getName() == "macos" && GetSDKInfo() && + (!Introduced.Version.empty() || !Deprecated.Version.empty() || + !Obsoleted.Version.empty())) { + if (const auto *MacOStoMacCatalystMapping = + GetSDKInfo()->getVersionMapping( + DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) { + // Infer Mac Catalyst availability from the macOS availability attribute + // if it has versioned availability. Don't infer 'unavailable'. This + // inferred availability has lower priority than the other availability + // attributes that are inferred from 'ios'. + NewII = &S.Context.Idents.get("maccatalyst"); + auto RemapMacOSVersion = + [&](const VersionTuple &V) -> Optional<VersionTuple> { + if (V.empty()) + return None; + // API_TO_BE_DEPRECATED is 100000. + if (V.getMajor() == 100000) + return VersionTuple(100000); + // The minimum iosmac version is 13.1 + return MacOStoMacCatalystMapping->map(V, VersionTuple(13, 1), None); + }; + Optional<VersionTuple> NewIntroduced = + RemapMacOSVersion(Introduced.Version), + NewDeprecated = + RemapMacOSVersion(Deprecated.Version), + NewObsoleted = + RemapMacOSVersion(Obsoleted.Version); + if (NewIntroduced || NewDeprecated || NewObsoleted) { + auto VersionOrEmptyVersion = + [](const Optional<VersionTuple> &V) -> VersionTuple { + return V ? *V : VersionTuple(); + }; + AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr( + ND, AL.getRange(), NewII, true /*Implicit*/, + VersionOrEmptyVersion(NewIntroduced), + VersionOrEmptyVersion(NewDeprecated), + VersionOrEmptyVersion(NewObsoleted), /*IsUnavailable=*/false, Str, + IsStrict, Replacement, Sema::AMK_None, + PriorityModifier + Sema::AP_InferredFromOtherPlatform + + Sema::AP_InferredFromOtherPlatform); + if (NewAttr) + D->addAttr(NewAttr); + } + } + } } } static void handleExternalSourceSymbolAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (!checkAttributeAtLeastNumArgs(S, AL, 1)) + if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 3)) return; - assert(checkAttributeAtMostNumArgs(S, AL, 3) && - "Invalid number of arguments in an external_source_symbol attribute"); StringRef Language; if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getArgAsExpr(0))) @@ -2693,11 +2731,6 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const ParsedAttr &AL, D->addAttr(newAttr); } -static void handleObjCNonRuntimeProtocolAttr(Sema &S, Decl *D, - const ParsedAttr &AL) { - handleSimpleAttribute<ObjCNonRuntimeProtocolAttr>(S, D, AL); -} - static void handleObjCDirectAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // objc_direct cannot be set on methods declared in the context of a protocol if (isa<ObjCProtocolDecl>(D->getDeclContext())) { @@ -2872,8 +2905,10 @@ static void handleSentinelAttr(Sema &S, Decl *D, const ParsedAttr &AL) { QualType Ty = V->getType(); if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) { const FunctionType *FT = Ty->isFunctionPointerType() - ? D->getFunctionType() - : Ty->castAs<BlockPointerType>()->getPointeeType()->getAs<FunctionType>(); + ? D->getFunctionType() + : Ty->castAs<BlockPointerType>() + ->getPointeeType() + ->castAs<FunctionType>(); if (!cast<FunctionProtoType>(FT)->isVariadic()) { int m = Ty->isFunctionPointerType() ? 0 : 1; S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << m; @@ -2906,7 +2941,7 @@ static void handleWarnUnusedResult(Sema &S, Decl *D, const ParsedAttr &AL) { } StringRef Str; - if ((AL.isCXX11Attribute() || AL.isC2xAttribute()) && !AL.getScopeName()) { + if (AL.isStandardAttributeSyntax() && !AL.getScopeName()) { // The standard attribute cannot be applied to variable declarations such // as a function pointer. if (isa<VarDecl>(D)) @@ -3051,11 +3086,31 @@ SectionAttr *Sema::mergeSectionAttr(Decl *D, const AttributeCommonInfo &CI, return ::new (Context) SectionAttr(Context, CI, Name); } +/// Used to implement to perform semantic checking on +/// attribute((section("foo"))) specifiers. +/// +/// In this case, "foo" is passed in to be checked. If the section +/// specifier is invalid, return an Error that indicates the problem. +/// +/// This is a simple quality of implementation feature to catch errors +/// and give good diagnostics in cases when the assembler or code generator +/// would otherwise reject the section specifier. +llvm::Error Sema::isValidSectionSpecifier(StringRef SecName) { + if (!Context.getTargetInfo().getTriple().isOSDarwin()) + return llvm::Error::success(); + + // Let MCSectionMachO validate this. + StringRef Segment, Section; + unsigned TAA, StubSize; + bool HasTAA; + return llvm::MCSectionMachO::ParseSectionSpecifier(SecName, Segment, Section, + TAA, HasTAA, StubSize); +} + bool Sema::checkSectionName(SourceLocation LiteralLoc, StringRef SecName) { - std::string Error = Context.getTargetInfo().isValidSectionSpecifier(SecName); - if (!Error.empty()) { - Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) << Error - << 1 /*'section'*/; + if (llvm::Error E = isValidSectionSpecifier(SecName)) { + Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) + << toString(std::move(E)) << 1 /*'section'*/; return false; } return true; @@ -3072,14 +3127,6 @@ static void handleSectionAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!S.checkSectionName(LiteralLoc, Str)) return; - // If the target wants to validate the section specifier, make it happen. - std::string Error = S.Context.getTargetInfo().isValidSectionSpecifier(Str); - if (!Error.empty()) { - S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) - << Error; - return; - } - SectionAttr *NewAttr = S.mergeSectionAttr(D, AL, Str); if (NewAttr) { D->addAttr(NewAttr); @@ -3095,11 +3142,9 @@ static void handleSectionAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // `#pragma code_seg("segname")` uses checkSectionName() instead. static bool checkCodeSegName(Sema &S, SourceLocation LiteralLoc, StringRef CodeSegName) { - std::string Error = - S.Context.getTargetInfo().isValidSectionSpecifier(CodeSegName); - if (!Error.empty()) { + if (llvm::Error E = S.isValidSectionSpecifier(CodeSegName)) { S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) - << Error << 0 /*'code-seg'*/; + << toString(std::move(E)) << 0 /*'code-seg'*/; return false; } @@ -3328,7 +3373,7 @@ static void handleFormatArgAttr(Sema &S, Decl *D, const ParsedAttr &AL) { return; } Ty = getFunctionOrMethodResultType(D); - if (!isNSStringType(Ty, S.Context) && + if (!isNSStringType(Ty, S.Context, /*AllowNSAttributedString=*/true) && !isCFStringType(Ty, S.Context) && (!Ty->isPointerType() || !Ty->castAs<PointerType>()->getPointeeType()->isCharType())) { @@ -3504,7 +3549,7 @@ static void handleFormatAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } else if (Kind == NSStringFormat) { // FIXME: do we need to check if the type is NSString*? What are the // semantics? - if (!isNSStringType(Ty, S.Context)) { + if (!isNSStringType(Ty, S.Context, /*AllowNSAttributedString=*/true)) { S.Diag(AL.getLoc(), diag::err_format_attribute_not) << "an NSString" << IdxExpr->getSourceRange() << getFunctionOrMethodParamRange(D, ArgIdx); @@ -3802,11 +3847,11 @@ void Sema::AddAnnotationAttr(Decl *D, const AttributeCommonInfo &CI, E = ImplicitCastExpr::Create(Context, Context.getPointerType(E->getType()), clang::CK_FunctionToPointerDecay, E, nullptr, - VK_RValue, FPOptionsOverride()); + VK_PRValue, FPOptionsOverride()); if (E->isLValue()) E = ImplicitCastExpr::Create(Context, E->getType().getNonReferenceType(), clang::CK_LValueToRValue, E, nullptr, - VK_RValue, FPOptionsOverride()); + VK_PRValue, FPOptionsOverride()); Expr::EvalResult Eval; Notes.clear(); @@ -3986,6 +4031,12 @@ void Sema::AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E, return; uint64_t AlignVal = Alignment.getZExtValue(); + // 16 byte ByVal alignment not due to a vector member is not honoured by XL + // on AIX. Emit a warning here that users are generating binary incompatible + // code to be safe. + if (AlignVal >= 16 && isa<FieldDecl>(D) && + Context.getTargetInfo().getTriple().isOSAIX()) + Diag(AttrLoc, diag::warn_not_xl_compatible) << E->getSourceRange(); // C++11 [dcl.align]p2: // -- if the constant expression evaluates to zero, the alignment @@ -4350,20 +4401,6 @@ AlwaysInlineAttr *Sema::mergeAlwaysInlineAttr(Decl *D, return ::new (Context) AlwaysInlineAttr(Context, CI); } -CommonAttr *Sema::mergeCommonAttr(Decl *D, const ParsedAttr &AL) { - if (checkAttrMutualExclusion<InternalLinkageAttr>(*this, D, AL)) - return nullptr; - - return ::new (Context) CommonAttr(Context, AL); -} - -CommonAttr *Sema::mergeCommonAttr(Decl *D, const CommonAttr &AL) { - if (checkAttrMutualExclusion<InternalLinkageAttr>(*this, D, AL)) - return nullptr; - - return ::new (Context) CommonAttr(Context, AL); -} - InternalLinkageAttr *Sema::mergeInternalLinkageAttr(Decl *D, const ParsedAttr &AL) { if (const auto *VD = dyn_cast<VarDecl>(D)) { @@ -4382,9 +4419,6 @@ InternalLinkageAttr *Sema::mergeInternalLinkageAttr(Decl *D, } } - if (checkAttrMutualExclusion<CommonAttr>(*this, D, AL)) - return nullptr; - return ::new (Context) InternalLinkageAttr(Context, AL); } InternalLinkageAttr * @@ -4405,9 +4439,6 @@ Sema::mergeInternalLinkageAttr(Decl *D, const InternalLinkageAttr &AL) { } } - if (checkAttrMutualExclusion<CommonAttr>(*this, D, AL)) - return nullptr; - return ::new (Context) InternalLinkageAttr(Context, AL); } @@ -4424,14 +4455,6 @@ MinSizeAttr *Sema::mergeMinSizeAttr(Decl *D, const AttributeCommonInfo &CI) { return ::new (Context) MinSizeAttr(Context, CI); } -NoSpeculativeLoadHardeningAttr *Sema::mergeNoSpeculativeLoadHardeningAttr( - Decl *D, const NoSpeculativeLoadHardeningAttr &AL) { - if (checkAttrMutualExclusion<SpeculativeLoadHardeningAttr>(*this, D, AL)) - return nullptr; - - return ::new (Context) NoSpeculativeLoadHardeningAttr(Context, AL); -} - SwiftNameAttr *Sema::mergeSwiftNameAttr(Decl *D, const SwiftNameAttr &SNA, StringRef Name) { if (const auto *PrevSNA = D->getAttr<SwiftNameAttr>()) { @@ -4465,18 +4488,7 @@ OptimizeNoneAttr *Sema::mergeOptimizeNoneAttr(Decl *D, return ::new (Context) OptimizeNoneAttr(Context, CI); } -SpeculativeLoadHardeningAttr *Sema::mergeSpeculativeLoadHardeningAttr( - Decl *D, const SpeculativeLoadHardeningAttr &AL) { - if (checkAttrMutualExclusion<NoSpeculativeLoadHardeningAttr>(*this, D, AL)) - return nullptr; - - return ::new (Context) SpeculativeLoadHardeningAttr(Context, AL); -} - static void handleAlwaysInlineAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (checkAttrMutualExclusion<NotTailCalledAttr>(S, D, AL)) - return; - if (AlwaysInlineAttr *Inline = S.mergeAlwaysInlineAttr(D, AL, AL.getAttrName())) D->addAttr(Inline); @@ -4493,21 +4505,22 @@ static void handleOptimizeNoneAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } static void handleConstantAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (checkAttrMutualExclusion<CUDASharedAttr>(S, D, AL) || - checkAttrMutualExclusion<HIPManagedAttr>(S, D, AL)) - return; const auto *VD = cast<VarDecl>(D); if (VD->hasLocalStorage()) { S.Diag(AL.getLoc(), diag::err_cuda_nonstatic_constdev); return; } + // constexpr variable may already get an implicit constant attr, which should + // be replaced by the explicit constant attr. + if (auto *A = D->getAttr<CUDAConstantAttr>()) { + if (!A->isImplicit()) + return; + D->dropAttr<CUDAConstantAttr>(); + } D->addAttr(::new (S.Context) CUDAConstantAttr(S.Context, AL)); } static void handleSharedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (checkAttrMutualExclusion<CUDAConstantAttr>(S, D, AL) || - checkAttrMutualExclusion<HIPManagedAttr>(S, D, AL)) - return; const auto *VD = cast<VarDecl>(D); // extern __shared__ is only allowed on arrays with no length (e.g. // "int x[]"). @@ -4524,10 +4537,6 @@ static void handleSharedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } static void handleGlobalAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (checkAttrMutualExclusion<CUDADeviceAttr>(S, D, AL) || - checkAttrMutualExclusion<CUDAHostAttr>(S, D, AL)) { - return; - } const auto *FD = cast<FunctionDecl>(D); if (!FD->getReturnType()->isVoidType() && !FD->getReturnType()->getAs<AutoType>() && @@ -4561,10 +4570,6 @@ static void handleGlobalAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } static void handleDeviceAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (checkAttrMutualExclusion<CUDAGlobalAttr>(S, D, AL)) { - return; - } - if (const auto *VD = dyn_cast<VarDecl>(D)) { if (VD->hasLocalStorage()) { S.Diag(AL.getLoc(), diag::err_cuda_nonstatic_constdev); @@ -4581,11 +4586,6 @@ static void handleDeviceAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } static void handleManagedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (checkAttrMutualExclusion<CUDAConstantAttr>(S, D, AL) || - checkAttrMutualExclusion<CUDASharedAttr>(S, D, AL)) { - return; - } - if (const auto *VD = dyn_cast<VarDecl>(D)) { if (VD->hasLocalStorage()) { S.Diag(AL.getLoc(), diag::err_cuda_nonstatic_constdev); @@ -4645,6 +4645,9 @@ static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) { case ParsedAttr::AT_SwiftCall: D->addAttr(::new (S.Context) SwiftCallAttr(S.Context, AL)); return; + case ParsedAttr::AT_SwiftAsyncCall: + D->addAttr(::new (S.Context) SwiftAsyncCallAttr(S.Context, AL)); + return; case ParsedAttr::AT_VectorCall: D->addAttr(::new (S.Context) VectorCallAttr(S.Context, AL)); return; @@ -4691,7 +4694,7 @@ static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } static void handleSuppressAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (!checkAttributeAtLeastNumArgs(S, AL, 1)) + if (!AL.checkAtLeastNumArgs(S, 1)) return; std::vector<StringRef> DiagnosticIdentifiers; @@ -4730,7 +4733,10 @@ static void handleLifetimeCategoryAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } // To check if earlier decl attributes do not conflict the newly parsed ones - // we always add (and check) the attribute to the cannonical decl. + // we always add (and check) the attribute to the cannonical decl. We need + // to repeat the check for attribute mutual exclusion because we're attaching + // all of the attributes to the canonical declaration rather than the current + // declaration. D = D->getCanonicalDecl(); if (AL.getKind() == ParsedAttr::AT_Owner) { if (checkAttrMutualExclusion<PointerAttr>(S, D, AL)) @@ -4781,7 +4787,7 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC, } unsigned ReqArgs = Attrs.getKind() == ParsedAttr::AT_Pcs ? 1 : 0; - if (!checkAttributeNumArgs(*this, Attrs, ReqArgs)) { + if (!Attrs.checkExactlyNumArgs(*this, ReqArgs)) { Attrs.setInvalid(); return true; } @@ -4806,6 +4812,9 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC, case ParsedAttr::AT_SwiftCall: CC = CC_Swift; break; + case ParsedAttr::AT_SwiftAsyncCall: + CC = CC_SwiftAsync; + break; case ParsedAttr::AT_VectorCall: CC = CC_X86VectorCall; break; @@ -4984,6 +4993,14 @@ void Sema::AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI, D->addAttr(::new (Context) SwiftContextAttr(Context, CI)); return; + case ParameterABI::SwiftAsyncContext: + if (!isValidSwiftContextType(type)) { + Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type) + << getParameterABISpelling(abi) << /*pointer to pointer */ 0 << type; + } + D->addAttr(::new (Context) SwiftAsyncContextAttr(Context, CI)); + return; + case ParameterABI::SwiftErrorResult: if (!isValidSwiftErrorResultType(type)) { Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type) @@ -5009,7 +5026,7 @@ bool Sema::CheckRegparmAttr(const ParsedAttr &AL, unsigned &numParams) { if (AL.isInvalid()) return true; - if (!checkAttributeNumArgs(*this, AL, 1)) { + if (!AL.checkExactlyNumArgs(*this, 1)) { AL.setInvalid(); return true; } @@ -5063,7 +5080,7 @@ static Expr *makeLaunchBoundsArgExpr(Sema &S, Expr *E, // Make sure we can fit it in 32 bits. if (!I->isIntN(32)) { S.Diag(E->getExprLoc(), diag::err_ice_too_large) - << I->toString(10, false) << 32 << /* Unsigned */ 1; + << toString(*I, 10, false) << 32 << /* Unsigned */ 1; return nullptr; } if (*I < 0) @@ -5098,8 +5115,7 @@ void Sema::AddLaunchBoundsAttr(Decl *D, const AttributeCommonInfo &CI, } static void handleLaunchBoundsAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (!checkAttributeAtLeastNumArgs(S, AL, 1) || - !checkAttributeAtMostNumArgs(S, AL, 2)) + if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 2)) return; S.AddLaunchBoundsAttr(D, AL, AL.getArgAsExpr(0), @@ -5146,7 +5162,7 @@ static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D, return; } - if (!checkAttributeNumArgs(S, AL, 1)) + if (!AL.checkExactlyNumArgs(S, 1)) return; if (!isa<VarDecl>(D)) { @@ -5237,15 +5253,12 @@ static bool ArmCdeAliasValid(unsigned BuiltinID, StringRef AliasName) { return ArmBuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames); } -static bool ArmSveAliasValid(unsigned BuiltinID, StringRef AliasName) { - switch (BuiltinID) { - default: - return false; -#define GET_SVE_BUILTINS -#define BUILTIN(name, types, attr) case SVE::BI##name: -#include "clang/Basic/arm_sve_builtins.inc" - return true; - } +static bool ArmSveAliasValid(ASTContext &Context, unsigned BuiltinID, + StringRef AliasName) { + if (Context.BuiltinInfo.isAuxBuiltinID(BuiltinID)) + BuiltinID = Context.BuiltinInfo.getAuxBuiltinID(BuiltinID); + return BuiltinID >= AArch64::FirstSVEBuiltin && + BuiltinID <= AArch64::LastSVEBuiltin; } static void handleArmBuiltinAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) { @@ -5260,7 +5273,7 @@ static void handleArmBuiltinAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) { StringRef AliasName = cast<FunctionDecl>(D)->getIdentifier()->getName(); bool IsAArch64 = S.Context.getTargetInfo().getTriple().isAArch64(); - if ((IsAArch64 && !ArmSveAliasValid(BuiltinID, AliasName)) || + if ((IsAArch64 && !ArmSveAliasValid(S.Context, BuiltinID, AliasName)) || (!IsAArch64 && !ArmMveAliasValid(BuiltinID, AliasName) && !ArmCdeAliasValid(BuiltinID, AliasName))) { S.Diag(AL.getLoc(), diag::err_attribute_arm_builtin_alias); @@ -5270,6 +5283,38 @@ static void handleArmBuiltinAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) { D->addAttr(::new (S.Context) ArmBuiltinAliasAttr(S.Context, AL, Ident)); } +static bool RISCVAliasValid(unsigned BuiltinID, StringRef AliasName) { + return BuiltinID >= Builtin::FirstTSBuiltin && + BuiltinID < RISCV::LastTSBuiltin; +} + +static void handleBuiltinAliasAttr(Sema &S, Decl *D, + const ParsedAttr &AL) { + if (!AL.isArgIdent(0)) { + S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) + << AL << 1 << AANT_ArgumentIdentifier; + return; + } + + IdentifierInfo *Ident = AL.getArgAsIdent(0)->Ident; + unsigned BuiltinID = Ident->getBuiltinID(); + StringRef AliasName = cast<FunctionDecl>(D)->getIdentifier()->getName(); + + bool IsAArch64 = S.Context.getTargetInfo().getTriple().isAArch64(); + bool IsARM = S.Context.getTargetInfo().getTriple().isARM(); + bool IsRISCV = S.Context.getTargetInfo().getTriple().isRISCV(); + if ((IsAArch64 && !ArmSveAliasValid(S.Context, BuiltinID, AliasName)) || + (IsARM && !ArmMveAliasValid(BuiltinID, AliasName) && + !ArmCdeAliasValid(BuiltinID, AliasName)) || + (IsRISCV && !RISCVAliasValid(BuiltinID, AliasName)) || + (!IsAArch64 && !IsARM && !IsRISCV)) { + S.Diag(AL.getLoc(), diag::err_attribute_builtin_alias) << AL; + return; + } + + D->addAttr(::new (S.Context) BuiltinAliasAttr(S.Context, AL, Ident)); +} + //===----------------------------------------------------------------------===// // Checker-specific attribute handlers. //===----------------------------------------------------------------------===// @@ -5751,9 +5796,11 @@ static void handleSwiftBridge(Sema &S, Decl *D, const ParsedAttr &AL) { if (!S.checkStringLiteralArgumentAttr(AL, 0, BT)) return; - // Don't duplicate annotations that are already set. - if (D->hasAttr<SwiftBridgeAttr>()) { - S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL; + // Warn about duplicate attributes if they have different arguments, but drop + // any duplicate attributes regardless. + if (const auto *Other = D->getAttr<SwiftBridgeAttr>()) { + if (Other->getSwiftType() != BT) + S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL; return; } @@ -5856,6 +5903,125 @@ static void handleSwiftError(Sema &S, Decl *D, const ParsedAttr &AL) { D->addAttr(::new (S.Context) SwiftErrorAttr(S.Context, AL, Convention)); } +static void checkSwiftAsyncErrorBlock(Sema &S, Decl *D, + const SwiftAsyncErrorAttr *ErrorAttr, + const SwiftAsyncAttr *AsyncAttr) { + if (AsyncAttr->getKind() == SwiftAsyncAttr::None) { + if (ErrorAttr->getConvention() != SwiftAsyncErrorAttr::None) { + S.Diag(AsyncAttr->getLocation(), + diag::err_swift_async_error_without_swift_async) + << AsyncAttr << isa<ObjCMethodDecl>(D); + } + return; + } + + const ParmVarDecl *HandlerParam = getFunctionOrMethodParam( + D, AsyncAttr->getCompletionHandlerIndex().getASTIndex()); + // handleSwiftAsyncAttr already verified the type is correct, so no need to + // double-check it here. + const auto *FuncTy = HandlerParam->getType() + ->castAs<BlockPointerType>() + ->getPointeeType() + ->getAs<FunctionProtoType>(); + ArrayRef<QualType> BlockParams; + if (FuncTy) + BlockParams = FuncTy->getParamTypes(); + + switch (ErrorAttr->getConvention()) { + case SwiftAsyncErrorAttr::ZeroArgument: + case SwiftAsyncErrorAttr::NonZeroArgument: { + uint32_t ParamIdx = ErrorAttr->getHandlerParamIdx(); + if (ParamIdx == 0 || ParamIdx > BlockParams.size()) { + S.Diag(ErrorAttr->getLocation(), + diag::err_attribute_argument_out_of_bounds) << ErrorAttr << 2; + return; + } + QualType ErrorParam = BlockParams[ParamIdx - 1]; + if (!ErrorParam->isIntegralType(S.Context)) { + StringRef ConvStr = + ErrorAttr->getConvention() == SwiftAsyncErrorAttr::ZeroArgument + ? "zero_argument" + : "nonzero_argument"; + S.Diag(ErrorAttr->getLocation(), diag::err_swift_async_error_non_integral) + << ErrorAttr << ConvStr << ParamIdx << ErrorParam; + return; + } + break; + } + case SwiftAsyncErrorAttr::NonNullError: { + bool AnyErrorParams = false; + for (QualType Param : BlockParams) { + // Check for NSError *. + if (const auto *ObjCPtrTy = Param->getAs<ObjCObjectPointerType>()) { + if (const auto *ID = ObjCPtrTy->getInterfaceDecl()) { + if (ID->getIdentifier() == S.getNSErrorIdent()) { + AnyErrorParams = true; + break; + } + } + } + // Check for CFError *. + if (const auto *PtrTy = Param->getAs<PointerType>()) { + if (const auto *RT = PtrTy->getPointeeType()->getAs<RecordType>()) { + if (S.isCFError(RT->getDecl())) { + AnyErrorParams = true; + break; + } + } + } + } + + if (!AnyErrorParams) { + S.Diag(ErrorAttr->getLocation(), + diag::err_swift_async_error_no_error_parameter) + << ErrorAttr << isa<ObjCMethodDecl>(D); + return; + } + break; + } + case SwiftAsyncErrorAttr::None: + break; + } +} + +static void handleSwiftAsyncError(Sema &S, Decl *D, const ParsedAttr &AL) { + IdentifierLoc *IDLoc = AL.getArgAsIdent(0); + SwiftAsyncErrorAttr::ConventionKind ConvKind; + if (!SwiftAsyncErrorAttr::ConvertStrToConventionKind(IDLoc->Ident->getName(), + ConvKind)) { + S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) + << AL << IDLoc->Ident; + return; + } + + uint32_t ParamIdx = 0; + switch (ConvKind) { + case SwiftAsyncErrorAttr::ZeroArgument: + case SwiftAsyncErrorAttr::NonZeroArgument: { + if (!AL.checkExactlyNumArgs(S, 2)) + return; + + Expr *IdxExpr = AL.getArgAsExpr(1); + if (!checkUInt32Argument(S, AL, IdxExpr, ParamIdx)) + return; + break; + } + case SwiftAsyncErrorAttr::NonNullError: + case SwiftAsyncErrorAttr::None: { + if (!AL.checkExactlyNumArgs(S, 1)) + return; + break; + } + } + + auto *ErrorAttr = + ::new (S.Context) SwiftAsyncErrorAttr(S.Context, AL, ConvKind, ParamIdx); + D->addAttr(ErrorAttr); + + if (auto *AsyncAttr = D->getAttr<SwiftAsyncAttr>()) + checkSwiftAsyncErrorBlock(S, D, ErrorAttr, AsyncAttr); +} + // For a function, this will validate a compound Swift name, e.g. // <code>init(foo:bar:baz:)</code> or <code>controllerForName(_:)</code>, and // the function will output the number of parameter names, and whether this is a @@ -6168,7 +6334,7 @@ static void handleSwiftAsyncName(Sema &S, Decl *D, const ParsedAttr &AL) { static void handleSwiftNewType(Sema &S, Decl *D, const ParsedAttr &AL) { // Make sure that there is an identifier as the annotation's single argument. - if (!checkAttributeNumArgs(S, AL, 1)) + if (!AL.checkExactlyNumArgs(S, 1)) return; if (!AL.isArgIdent(0)) { @@ -6210,11 +6376,11 @@ static void handleSwiftAsyncAttr(Sema &S, Decl *D, const ParsedAttr &AL) { ParamIdx Idx; if (Kind == SwiftAsyncAttr::None) { // If this is 'none', then there shouldn't be any additional arguments. - if (!checkAttributeNumArgs(S, AL, 1)) + if (!AL.checkExactlyNumArgs(S, 1)) return; } else { // Non-none swift_async requires a completion handler index argument. - if (!checkAttributeNumArgs(S, AL, 2)) + if (!AL.checkExactlyNumArgs(S, 2)) return; Expr *HandlerIdx = AL.getArgAsExpr(1); @@ -6231,8 +6397,8 @@ static void handleSwiftAsyncAttr(Sema &S, Decl *D, const ParsedAttr &AL) { return; } QualType BlockTy = - CompletionBlockType->getAs<BlockPointerType>()->getPointeeType(); - if (!BlockTy->getAs<FunctionType>()->getReturnType()->isVoidType()) { + CompletionBlockType->castAs<BlockPointerType>()->getPointeeType(); + if (!BlockTy->castAs<FunctionType>()->getReturnType()->isVoidType()) { S.Diag(CompletionBlock->getLocation(), diag::err_swift_async_bad_block_type) << CompletionBlock->getType(); @@ -6240,7 +6406,12 @@ static void handleSwiftAsyncAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } } - D->addAttr(::new (S.Context) SwiftAsyncAttr(S.Context, AL, Kind, Idx)); + auto *AsyncAttr = + ::new (S.Context) SwiftAsyncAttr(S.Context, AL, Kind, Idx); + D->addAttr(AsyncAttr); + + if (auto *ErrorAttr = D->getAttr<SwiftAsyncErrorAttr>()) + checkSwiftAsyncErrorBlock(S, D, ErrorAttr, AsyncAttr); } //===----------------------------------------------------------------------===// @@ -6373,7 +6544,7 @@ static void handleAbiTagAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } if (AL.getNumArgs() == 0) Tags.push_back(NS->getName()); - } else if (!checkAttributeAtLeastNumArgs(S, AL, 1)) + } else if (!AL.checkAtLeastNumArgs(S, 1)) return; // Store tags sorted and without duplicates. @@ -6431,7 +6602,7 @@ static void handleMSP430InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } // The attribute takes one integer argument. - if (!checkAttributeNumArgs(S, AL, 1)) + if (!AL.checkExactlyNumArgs(S, 1)) return; if (!AL.isArgExpr(0)) { @@ -6503,6 +6674,8 @@ static void handleMipsInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { return; } + // We still have to do this manually because the Interrupt attributes are + // a bit special due to sharing their spellings across targets. if (checkAttrMutualExclusion<Mips16Attr>(S, D, AL)) return; @@ -6516,6 +6689,39 @@ static void handleMipsInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { D->addAttr(::new (S.Context) MipsInterruptAttr(S.Context, AL, Kind)); } +static void handleM68kInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + if (!AL.checkExactlyNumArgs(S, 1)) + return; + + if (!AL.isArgExpr(0)) { + S.Diag(AL.getLoc(), diag::err_attribute_argument_type) + << AL << AANT_ArgumentIntegerConstant; + return; + } + + // FIXME: Check for decl - it should be void ()(void). + + Expr *NumParamsExpr = static_cast<Expr *>(AL.getArgAsExpr(0)); + auto MaybeNumParams = NumParamsExpr->getIntegerConstantExpr(S.Context); + if (!MaybeNumParams) { + S.Diag(AL.getLoc(), diag::err_attribute_argument_type) + << AL << AANT_ArgumentIntegerConstant + << NumParamsExpr->getSourceRange(); + return; + } + + unsigned Num = MaybeNumParams->getLimitedValue(255); + if ((Num & 1) || Num > 30) { + S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) + << AL << (int)MaybeNumParams->getSExtValue() + << NumParamsExpr->getSourceRange(); + return; + } + + D->addAttr(::new (S.Context) M68kInterruptAttr(S.Context, AL, Num)); + D->addAttr(UsedAttr::CreateImplicit(S.Context)); +} + static void handleAnyX86InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // Semantic checks for a function with the 'interrupt' attribute. // a) Must be a function. @@ -6587,7 +6793,7 @@ static void handleAVRInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { return; } - if (!checkAttributeNumArgs(S, AL, 0)) + if (!AL.checkExactlyNumArgs(S, 0)) return; handleSimpleAttribute<AVRInterruptAttr>(S, D, AL); @@ -6600,7 +6806,7 @@ static void handleAVRSignalAttr(Sema &S, Decl *D, const ParsedAttr &AL) { return; } - if (!checkAttributeNumArgs(S, AL, 0)) + if (!AL.checkExactlyNumArgs(S, 0)) return; handleSimpleAttribute<AVRSignalAttr>(S, D, AL); @@ -6731,7 +6937,7 @@ static void handleRISCVInterruptAttr(Sema &S, Decl *D, } // Check the attribute argument. Argument is optional. - if (!checkAttributeAtMostNumArgs(S, AL, 1)) + if (!AL.checkAtMostNumArgs(S, 1)) return; StringRef Str; @@ -6788,6 +6994,9 @@ static void handleInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { case llvm::Triple::mips: handleMipsInterruptAttr(S, D, AL); break; + case llvm::Triple::m68k: + handleM68kInterruptAttr(S, D, AL); + break; case llvm::Triple::x86: case llvm::Triple::x86_64: handleAnyX86InterruptAttr(S, D, AL); @@ -6901,8 +7110,7 @@ void Sema::addAMDGPUWavesPerEUAttr(Decl *D, const AttributeCommonInfo &CI, } static void handleAMDGPUWavesPerEUAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (!checkAttributeAtLeastNumArgs(S, AL, 1) || - !checkAttributeAtMostNumArgs(S, AL, 2)) + if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 2)) return; Expr *MinExpr = AL.getArgAsExpr(0); @@ -7125,7 +7333,7 @@ static void handleReleaseCapabilityAttr(Sema &S, Decl *D, static void handleRequiresCapabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (!checkAttributeAtLeastNumArgs(S, AL, 1)) + if (!AL.checkAtLeastNumArgs(S, 1)) return; // check that all arguments are lockable objects @@ -7149,6 +7357,11 @@ static void handleDeprecatedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // namespace. return; } + } else if (isa<UsingDecl, UnresolvedUsingTypenameDecl, + UnresolvedUsingValueDecl>(D)) { + S.Diag(AL.getRange().getBegin(), diag::warn_deprecated_ignored_on_using) + << AL; + return; } // Handle the cases where the attribute has a text message. @@ -7157,9 +7370,9 @@ static void handleDeprecatedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { !S.checkStringLiteralArgumentAttr(AL, 0, Str)) return; - // Only support a single optional message for Declspec and CXX11. - if (AL.isDeclspecAttribute() || AL.isCXX11Attribute()) - checkAttributeAtMostNumArgs(S, AL, 1); + // Support a single optional message only for Declspec and [[]] spellings. + if (AL.isDeclspecAttribute() || AL.isStandardAttributeSyntax()) + AL.checkAtMostNumArgs(S, 1); else if (AL.isArgExpr(1) && AL.getArgAsExpr(1) && !S.checkStringLiteralArgumentAttr(AL, 1, Replacement)) return; @@ -7177,7 +7390,7 @@ static bool isGlobalVar(const Decl *D) { } static void handleNoSanitizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (!checkAttributeAtLeastNumArgs(S, AL, 1)) + if (!AL.checkAtLeastNumArgs(S, 1)) return; std::vector<StringRef> Sanitizers; @@ -7190,7 +7403,8 @@ static void handleNoSanitizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { return; if (parseSanitizerValue(SanitizerName, /*AllowGroups=*/true) == - SanitizerMask()) + SanitizerMask() && + SanitizerName != "coverage") S.Diag(LiteralLoc, diag::warn_unknown_sanitizer_ignored) << SanitizerName; else if (isGlobalVar(D) && SanitizerName != "address") S.Diag(D->getLocation(), diag::err_attribute_wrong_decl_type) @@ -7224,7 +7438,7 @@ static void handleNoSanitizeSpecificAttr(Sema &S, Decl *D, // getSpelling() or prettyPrint() on the resulting semantic attribute object // without failing assertions. unsigned TranslatedSpellingIndex = 0; - if (AL.isC2xAttribute() || AL.isCXX11Attribute()) + if (AL.isStandardAttributeSyntax()) TranslatedSpellingIndex = 1; AttributeCommonInfo Info = AL; @@ -7247,49 +7461,6 @@ static void handleOpenCLNoSVMAttr(Sema &S, Decl *D, const ParsedAttr &AL) { << "2.0"; } -/// Handles semantic checking for features that are common to all attributes, -/// such as checking whether a parameter was properly specified, or the correct -/// number of arguments were passed, etc. -static bool handleCommonAttributeFeatures(Sema &S, Decl *D, - const ParsedAttr &AL) { - // Several attributes carry different semantics than the parsing requires, so - // those are opted out of the common argument checks. - // - // We also bail on unknown and ignored attributes because those are handled - // as part of the target-specific handling logic. - if (AL.getKind() == ParsedAttr::UnknownAttribute) - return false; - // Check whether the attribute requires specific language extensions to be - // enabled. - if (!AL.diagnoseLangOpts(S)) - return true; - // Check whether the attribute appertains to the given subject. - if (!AL.diagnoseAppertainsTo(S, D)) - return true; - if (AL.hasCustomParsing()) - return false; - - if (AL.getMinArgs() == AL.getMaxArgs()) { - // If there are no optional arguments, then checking for the argument count - // is trivial. - if (!checkAttributeNumArgs(S, AL, AL.getMinArgs())) - return true; - } else { - // There are optional arguments, so checking is slightly more involved. - if (AL.getMinArgs() && - !checkAttributeAtLeastNumArgs(S, AL, AL.getMinArgs())) - return true; - else if (!AL.hasVariadicArg() && AL.getMaxArgs() && - !checkAttributeAtMostNumArgs(S, AL, AL.getMaxArgs())) - return true; - } - - if (S.CheckAttrTarget(AL)) - return true; - - return false; -} - static void handleOpenCLAccessAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (D->isInvalidDecl()) return; @@ -7308,16 +7479,24 @@ static void handleOpenCLAccessAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } } - // OpenCL v2.0 s6.6 - read_write can be used for image types to specify that an - // image object can be read and written. - // OpenCL v2.0 s6.13.6 - A kernel cannot read from and write to the same pipe - // object. Using the read_write (or __read_write) qualifier with the pipe - // qualifier is a compilation error. + // OpenCL v2.0 s6.6 - read_write can be used for image types to specify that + // an image object can be read and written. OpenCL v2.0 s6.13.6 - A kernel + // cannot read from and write to the same pipe object. Using the read_write + // (or __read_write) qualifier with the pipe qualifier is a compilation error. + // OpenCL v3.0 s6.8 - For OpenCL C 2.0, or with the + // __opencl_c_read_write_images feature, image objects specified as arguments + // to a kernel can additionally be declared to be read-write. + // C++ for OpenCL inherits rule from OpenCL C v2.0. if (const auto *PDecl = dyn_cast<ParmVarDecl>(D)) { const Type *DeclTy = PDecl->getType().getCanonicalType().getTypePtr(); if (AL.getAttrName()->getName().find("read_write") != StringRef::npos) { + bool ReadWriteImagesUnsupportedForOCLC = + (S.getLangOpts().OpenCLVersion < 200) || + (S.getLangOpts().OpenCLVersion == 300 && + !S.getOpenCLOptions().isSupported("__opencl_c_read_write_images", + S.getLangOpts())); if ((!S.getLangOpts().OpenCLCPlusPlus && - S.getLangOpts().OpenCLVersion < 200) || + ReadWriteImagesUnsupportedForOCLC) || DeclTy->isPipeType()) { S.Diag(AL.getLoc(), diag::err_opencl_invalid_read_write) << AL << PDecl->getType() << DeclTy->isImageType(); @@ -7377,9 +7556,9 @@ static void handleDestroyAttr(Sema &S, Decl *D, const ParsedAttr &A) { } if (A.getKind() == ParsedAttr::AT_AlwaysDestroy) - handleSimpleAttributeWithExclusions<AlwaysDestroyAttr, NoDestroyAttr>(S, D, A); + handleSimpleAttribute<AlwaysDestroyAttr>(S, D, A); else - handleSimpleAttributeWithExclusions<NoDestroyAttr, AlwaysDestroyAttr>(S, D, A); + handleSimpleAttribute<NoDestroyAttr>(S, D, A); } static void handleUninitializedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { @@ -7643,7 +7822,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, return; } - if (handleCommonAttributeFeatures(S, D, AL)) + if (S.checkCommonAttributeFeatures(D, AL)) return; switch (AL.getKind()) { @@ -7655,6 +7834,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, assert(AL.isTypeAttr() && "Non-type attribute not handled"); break; } + // N.B., ClangAttrEmitter.cpp emits a diagnostic helper that ensures a + // statement attribute is not written on a declaration, but this code is + // needed for attributes in Attr.td that do not list any subjects. S.Diag(AL.getLoc(), diag::err_stmt_attribute_invalid_on_decl) << AL << D->getLocation(); break; @@ -7668,21 +7850,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_DLLImport: handleDLLAttr(S, D, AL); break; - case ParsedAttr::AT_Mips16: - handleSimpleAttributeWithExclusions<Mips16Attr, MicroMipsAttr, - MipsInterruptAttr>(S, D, AL); - break; - case ParsedAttr::AT_MicroMips: - handleSimpleAttributeWithExclusions<MicroMipsAttr, Mips16Attr>(S, D, AL); - break; - case ParsedAttr::AT_MipsLongCall: - handleSimpleAttributeWithExclusions<MipsLongCallAttr, MipsShortCallAttr>( - S, D, AL); - break; - case ParsedAttr::AT_MipsShortCall: - handleSimpleAttributeWithExclusions<MipsShortCallAttr, MipsLongCallAttr>( - S, D, AL); - break; case ParsedAttr::AT_AMDGPUFlatWorkGroupSize: handleAMDGPUFlatWorkGroupSizeAttr(S, D, AL); break; @@ -7816,22 +7983,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_CUDADevice: handleDeviceAttr(S, D, AL); break; - case ParsedAttr::AT_CUDAHost: - handleSimpleAttributeWithExclusions<CUDAHostAttr, CUDAGlobalAttr>(S, D, AL); - break; case ParsedAttr::AT_HIPManaged: handleManagedAttr(S, D, AL); break; - case ParsedAttr::AT_CUDADeviceBuiltinSurfaceType: - handleSimpleAttributeWithExclusions<CUDADeviceBuiltinSurfaceTypeAttr, - CUDADeviceBuiltinTextureTypeAttr>(S, D, - AL); - break; - case ParsedAttr::AT_CUDADeviceBuiltinTextureType: - handleSimpleAttributeWithExclusions<CUDADeviceBuiltinTextureTypeAttr, - CUDADeviceBuiltinSurfaceTypeAttr>(S, D, - AL); - break; case ParsedAttr::AT_GNUInline: handleGNUInlineAttr(S, D, AL); break; @@ -7865,12 +8019,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_Ownership: handleOwnershipAttr(S, D, AL); break; - case ParsedAttr::AT_Cold: - handleSimpleAttributeWithExclusions<ColdAttr, HotAttr>(S, D, AL); - break; - case ParsedAttr::AT_Hot: - handleSimpleAttributeWithExclusions<HotAttr, ColdAttr>(S, D, AL); - break; case ParsedAttr::AT_Naked: handleNakedAttr(S, D, AL); break; @@ -7880,9 +8028,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_AnyX86NoCfCheck: handleNoCfCheckAttr(S, D, AL); break; - case ParsedAttr::AT_Leaf: - handleSimpleAttribute<LeafAttr>(S, D, AL); - break; case ParsedAttr::AT_NoThrow: if (!AL.isUsedAsTypeAttr()) handleSimpleAttribute<NoThrowAttr>(S, D, AL); @@ -7926,14 +8071,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_NSErrorDomain: handleNSErrorDomain(S, D, AL); break; - case ParsedAttr::AT_CFAuditedTransfer: - handleSimpleAttributeWithExclusions<CFAuditedTransferAttr, - CFUnknownTransferAttr>(S, D, AL); - break; - case ParsedAttr::AT_CFUnknownTransfer: - handleSimpleAttributeWithExclusions<CFUnknownTransferAttr, - CFAuditedTransferAttr>(S, D, AL); - break; case ParsedAttr::AT_CFConsumed: case ParsedAttr::AT_NSConsumed: case ParsedAttr::AT_OSConsumed: @@ -7974,10 +8111,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleVecTypeHint(S, D, AL); break; case ParsedAttr::AT_InitPriority: - if (S.Context.getTargetInfo().getTriple().isOSAIX()) - llvm::report_fatal_error( - "'init_priority' attribute is not yet supported on AIX"); - else handleInitPriorityAttr(S, D, AL); break; case ParsedAttr::AT_Packed: @@ -7989,15 +8122,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_Section: handleSectionAttr(S, D, AL); break; - case ParsedAttr::AT_SpeculativeLoadHardening: - handleSimpleAttributeWithExclusions<SpeculativeLoadHardeningAttr, - NoSpeculativeLoadHardeningAttr>(S, D, - AL); - break; - case ParsedAttr::AT_NoSpeculativeLoadHardening: - handleSimpleAttributeWithExclusions<NoSpeculativeLoadHardeningAttr, - SpeculativeLoadHardeningAttr>(S, D, AL); - break; case ParsedAttr::AT_CodeSeg: handleCodeSegAttr(S, D, AL); break; @@ -8016,9 +8140,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_ObjCDirect: handleObjCDirectAttr(S, D, AL); break; - case ParsedAttr::AT_ObjCNonRuntimeProtocol: - handleObjCNonRuntimeProtocolAttr(S, D, AL); - break; case ParsedAttr::AT_ObjCDirectMembers: handleObjCDirectMembersAttr(S, D, AL); handleSimpleAttribute<ObjCDirectMembersAttr>(S, D, AL); @@ -8029,17 +8150,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_Unused: handleUnusedAttr(S, D, AL); break; - case ParsedAttr::AT_NotTailCalled: - handleSimpleAttributeWithExclusions<NotTailCalledAttr, AlwaysInlineAttr>( - S, D, AL); - break; - case ParsedAttr::AT_DisableTailCalls: - handleSimpleAttributeWithExclusions<DisableTailCallsAttr, NakedAttr>(S, D, - AL); - break; - case ParsedAttr::AT_NoMerge: - handleSimpleAttribute<NoMergeAttr>(S, D, AL); - break; case ParsedAttr::AT_Visibility: handleVisibilityAttr(S, D, AL, false); break; @@ -8089,6 +8199,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_Pascal: case ParsedAttr::AT_RegCall: case ParsedAttr::AT_SwiftCall: + case ParsedAttr::AT_SwiftAsyncCall: case ParsedAttr::AT_VectorCall: case ParsedAttr::AT_MSABI: case ParsedAttr::AT_SysVABI: @@ -8115,6 +8226,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_SwiftContext: S.AddParameterABIAttr(D, AL, ParameterABI::SwiftContext); break; + case ParsedAttr::AT_SwiftAsyncContext: + S.AddParameterABIAttr(D, AL, ParameterABI::SwiftAsyncContext); + break; case ParsedAttr::AT_SwiftErrorResult: S.AddParameterABIAttr(D, AL, ParameterABI::SwiftErrorResult); break; @@ -8247,9 +8361,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_SwiftBridge: handleSwiftBridge(S, D, AL); break; - case ParsedAttr::AT_SwiftBridgedTypedef: - handleSimpleAttribute<SwiftBridgedTypedefAttr>(S, D, AL); - break; case ParsedAttr::AT_SwiftError: handleSwiftError(S, D, AL); break; @@ -8259,15 +8370,12 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_SwiftNewType: handleSwiftNewType(S, D, AL); break; - case ParsedAttr::AT_SwiftObjCMembers: - handleSimpleAttribute<SwiftObjCMembersAttr>(S, D, AL); - break; - case ParsedAttr::AT_SwiftPrivate: - handleSimpleAttribute<SwiftPrivateAttr>(S, D, AL); - break; case ParsedAttr::AT_SwiftAsync: handleSwiftAsyncAttr(S, D, AL); break; + case ParsedAttr::AT_SwiftAsyncError: + handleSwiftAsyncError(S, D, AL); + break; // XRay attributes. case ParsedAttr::AT_XRayLogArgs: @@ -8287,10 +8395,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleUninitializedAttr(S, D, AL); break; - case ParsedAttr::AT_LoaderUninitialized: - handleSimpleAttribute<LoaderUninitializedAttr>(S, D, AL); - break; - case ParsedAttr::AT_ObjCExternallyRetained: handleObjCExternallyRetainedAttr(S, D, AL); break; @@ -8326,6 +8430,14 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_EnforceTCBLeaf: handleEnforceTCBAttr<EnforceTCBLeafAttr, EnforceTCBAttr>(S, D, AL); break; + + case ParsedAttr::AT_BuiltinAlias: + handleBuiltinAliasAttr(S, D, AL); + break; + + case ParsedAttr::AT_UsingIfExists: + handleSimpleAttribute<UsingIfExistsAttr>(S, D, AL); + break; } } |