17330f729Sjoerg //===--- SemaDeclAttr.cpp - Declaration Attribute Handling ----------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // This file implements decl-related attribute processing.
107330f729Sjoerg //
117330f729Sjoerg //===----------------------------------------------------------------------===//
127330f729Sjoerg
137330f729Sjoerg #include "clang/AST/ASTConsumer.h"
147330f729Sjoerg #include "clang/AST/ASTContext.h"
157330f729Sjoerg #include "clang/AST/ASTMutationListener.h"
167330f729Sjoerg #include "clang/AST/CXXInheritance.h"
177330f729Sjoerg #include "clang/AST/DeclCXX.h"
187330f729Sjoerg #include "clang/AST/DeclObjC.h"
197330f729Sjoerg #include "clang/AST/DeclTemplate.h"
207330f729Sjoerg #include "clang/AST/Expr.h"
217330f729Sjoerg #include "clang/AST/ExprCXX.h"
227330f729Sjoerg #include "clang/AST/Mangle.h"
237330f729Sjoerg #include "clang/AST/RecursiveASTVisitor.h"
24*e038c9c4Sjoerg #include "clang/AST/Type.h"
257330f729Sjoerg #include "clang/Basic/CharInfo.h"
26*e038c9c4Sjoerg #include "clang/Basic/SourceLocation.h"
277330f729Sjoerg #include "clang/Basic/SourceManager.h"
287330f729Sjoerg #include "clang/Basic/TargetBuiltins.h"
297330f729Sjoerg #include "clang/Basic/TargetInfo.h"
307330f729Sjoerg #include "clang/Lex/Preprocessor.h"
317330f729Sjoerg #include "clang/Sema/DeclSpec.h"
327330f729Sjoerg #include "clang/Sema/DelayedDiagnostic.h"
337330f729Sjoerg #include "clang/Sema/Initialization.h"
347330f729Sjoerg #include "clang/Sema/Lookup.h"
35*e038c9c4Sjoerg #include "clang/Sema/ParsedAttr.h"
367330f729Sjoerg #include "clang/Sema/Scope.h"
377330f729Sjoerg #include "clang/Sema/ScopeInfo.h"
387330f729Sjoerg #include "clang/Sema/SemaInternal.h"
39*e038c9c4Sjoerg #include "llvm/ADT/Optional.h"
407330f729Sjoerg #include "llvm/ADT/STLExtras.h"
417330f729Sjoerg #include "llvm/ADT/StringExtras.h"
42*e038c9c4Sjoerg #include "llvm/IR/Assumptions.h"
43*e038c9c4Sjoerg #include "llvm/MC/MCSectionMachO.h"
44*e038c9c4Sjoerg #include "llvm/Support/Error.h"
457330f729Sjoerg #include "llvm/Support/MathExtras.h"
46*e038c9c4Sjoerg #include "llvm/Support/raw_ostream.h"
477330f729Sjoerg
487330f729Sjoerg using namespace clang;
497330f729Sjoerg using namespace sema;
507330f729Sjoerg
517330f729Sjoerg namespace AttributeLangSupport {
527330f729Sjoerg enum LANG {
537330f729Sjoerg C,
547330f729Sjoerg Cpp,
557330f729Sjoerg ObjC
567330f729Sjoerg };
577330f729Sjoerg } // end namespace AttributeLangSupport
587330f729Sjoerg
597330f729Sjoerg //===----------------------------------------------------------------------===//
607330f729Sjoerg // Helper functions
617330f729Sjoerg //===----------------------------------------------------------------------===//
627330f729Sjoerg
637330f729Sjoerg /// isFunctionOrMethod - Return true if the given decl has function
647330f729Sjoerg /// type (function or function-typed variable) or an Objective-C
657330f729Sjoerg /// method.
isFunctionOrMethod(const Decl * D)667330f729Sjoerg static bool isFunctionOrMethod(const Decl *D) {
677330f729Sjoerg return (D->getFunctionType() != nullptr) || isa<ObjCMethodDecl>(D);
687330f729Sjoerg }
697330f729Sjoerg
707330f729Sjoerg /// Return true if the given decl has function type (function or
717330f729Sjoerg /// function-typed variable) or an Objective-C method or a block.
isFunctionOrMethodOrBlock(const Decl * D)727330f729Sjoerg static bool isFunctionOrMethodOrBlock(const Decl *D) {
737330f729Sjoerg return isFunctionOrMethod(D) || isa<BlockDecl>(D);
747330f729Sjoerg }
757330f729Sjoerg
767330f729Sjoerg /// Return true if the given decl has a declarator that should have
777330f729Sjoerg /// been processed by Sema::GetTypeForDeclarator.
hasDeclarator(const Decl * D)787330f729Sjoerg static bool hasDeclarator(const Decl *D) {
797330f729Sjoerg // In some sense, TypedefDecl really *ought* to be a DeclaratorDecl.
807330f729Sjoerg return isa<DeclaratorDecl>(D) || isa<BlockDecl>(D) || isa<TypedefNameDecl>(D) ||
817330f729Sjoerg isa<ObjCPropertyDecl>(D);
827330f729Sjoerg }
837330f729Sjoerg
847330f729Sjoerg /// hasFunctionProto - Return true if the given decl has a argument
857330f729Sjoerg /// information. This decl should have already passed
867330f729Sjoerg /// isFunctionOrMethod or isFunctionOrMethodOrBlock.
hasFunctionProto(const Decl * D)877330f729Sjoerg static bool hasFunctionProto(const Decl *D) {
887330f729Sjoerg if (const FunctionType *FnTy = D->getFunctionType())
897330f729Sjoerg return isa<FunctionProtoType>(FnTy);
907330f729Sjoerg return isa<ObjCMethodDecl>(D) || isa<BlockDecl>(D);
917330f729Sjoerg }
927330f729Sjoerg
937330f729Sjoerg /// getFunctionOrMethodNumParams - Return number of function or method
947330f729Sjoerg /// parameters. It is an error to call this on a K&R function (use
957330f729Sjoerg /// hasFunctionProto first).
getFunctionOrMethodNumParams(const Decl * D)967330f729Sjoerg static unsigned getFunctionOrMethodNumParams(const Decl *D) {
977330f729Sjoerg if (const FunctionType *FnTy = D->getFunctionType())
987330f729Sjoerg return cast<FunctionProtoType>(FnTy)->getNumParams();
997330f729Sjoerg if (const auto *BD = dyn_cast<BlockDecl>(D))
1007330f729Sjoerg return BD->getNumParams();
1017330f729Sjoerg return cast<ObjCMethodDecl>(D)->param_size();
1027330f729Sjoerg }
1037330f729Sjoerg
getFunctionOrMethodParam(const Decl * D,unsigned Idx)1047330f729Sjoerg static const ParmVarDecl *getFunctionOrMethodParam(const Decl *D,
1057330f729Sjoerg unsigned Idx) {
1067330f729Sjoerg if (const auto *FD = dyn_cast<FunctionDecl>(D))
1077330f729Sjoerg return FD->getParamDecl(Idx);
1087330f729Sjoerg if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
1097330f729Sjoerg return MD->getParamDecl(Idx);
1107330f729Sjoerg if (const auto *BD = dyn_cast<BlockDecl>(D))
1117330f729Sjoerg return BD->getParamDecl(Idx);
1127330f729Sjoerg return nullptr;
1137330f729Sjoerg }
1147330f729Sjoerg
getFunctionOrMethodParamType(const Decl * D,unsigned Idx)1157330f729Sjoerg static QualType getFunctionOrMethodParamType(const Decl *D, unsigned Idx) {
1167330f729Sjoerg if (const FunctionType *FnTy = D->getFunctionType())
1177330f729Sjoerg return cast<FunctionProtoType>(FnTy)->getParamType(Idx);
1187330f729Sjoerg if (const auto *BD = dyn_cast<BlockDecl>(D))
1197330f729Sjoerg return BD->getParamDecl(Idx)->getType();
1207330f729Sjoerg
1217330f729Sjoerg return cast<ObjCMethodDecl>(D)->parameters()[Idx]->getType();
1227330f729Sjoerg }
1237330f729Sjoerg
getFunctionOrMethodParamRange(const Decl * D,unsigned Idx)1247330f729Sjoerg static SourceRange getFunctionOrMethodParamRange(const Decl *D, unsigned Idx) {
1257330f729Sjoerg if (auto *PVD = getFunctionOrMethodParam(D, Idx))
1267330f729Sjoerg return PVD->getSourceRange();
1277330f729Sjoerg return SourceRange();
1287330f729Sjoerg }
1297330f729Sjoerg
getFunctionOrMethodResultType(const Decl * D)1307330f729Sjoerg static QualType getFunctionOrMethodResultType(const Decl *D) {
1317330f729Sjoerg if (const FunctionType *FnTy = D->getFunctionType())
1327330f729Sjoerg return FnTy->getReturnType();
1337330f729Sjoerg return cast<ObjCMethodDecl>(D)->getReturnType();
1347330f729Sjoerg }
1357330f729Sjoerg
getFunctionOrMethodResultSourceRange(const Decl * D)1367330f729Sjoerg static SourceRange getFunctionOrMethodResultSourceRange(const Decl *D) {
1377330f729Sjoerg if (const auto *FD = dyn_cast<FunctionDecl>(D))
1387330f729Sjoerg return FD->getReturnTypeSourceRange();
1397330f729Sjoerg if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
1407330f729Sjoerg return MD->getReturnTypeSourceRange();
1417330f729Sjoerg return SourceRange();
1427330f729Sjoerg }
1437330f729Sjoerg
isFunctionOrMethodVariadic(const Decl * D)1447330f729Sjoerg static bool isFunctionOrMethodVariadic(const Decl *D) {
1457330f729Sjoerg if (const FunctionType *FnTy = D->getFunctionType())
1467330f729Sjoerg return cast<FunctionProtoType>(FnTy)->isVariadic();
1477330f729Sjoerg if (const auto *BD = dyn_cast<BlockDecl>(D))
1487330f729Sjoerg return BD->isVariadic();
1497330f729Sjoerg return cast<ObjCMethodDecl>(D)->isVariadic();
1507330f729Sjoerg }
1517330f729Sjoerg
isInstanceMethod(const Decl * D)1527330f729Sjoerg static bool isInstanceMethod(const Decl *D) {
1537330f729Sjoerg if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(D))
1547330f729Sjoerg return MethodDecl->isInstance();
1557330f729Sjoerg return false;
1567330f729Sjoerg }
1577330f729Sjoerg
isNSStringType(QualType T,ASTContext & Ctx,bool AllowNSAttributedString=false)158*e038c9c4Sjoerg static inline bool isNSStringType(QualType T, ASTContext &Ctx,
159*e038c9c4Sjoerg bool AllowNSAttributedString = false) {
1607330f729Sjoerg const auto *PT = T->getAs<ObjCObjectPointerType>();
1617330f729Sjoerg if (!PT)
1627330f729Sjoerg return false;
1637330f729Sjoerg
1647330f729Sjoerg ObjCInterfaceDecl *Cls = PT->getObjectType()->getInterface();
1657330f729Sjoerg if (!Cls)
1667330f729Sjoerg return false;
1677330f729Sjoerg
1687330f729Sjoerg IdentifierInfo* ClsName = Cls->getIdentifier();
1697330f729Sjoerg
170*e038c9c4Sjoerg if (AllowNSAttributedString &&
171*e038c9c4Sjoerg ClsName == &Ctx.Idents.get("NSAttributedString"))
172*e038c9c4Sjoerg return true;
1737330f729Sjoerg // FIXME: Should we walk the chain of classes?
1747330f729Sjoerg return ClsName == &Ctx.Idents.get("NSString") ||
1757330f729Sjoerg ClsName == &Ctx.Idents.get("NSMutableString");
1767330f729Sjoerg }
1777330f729Sjoerg
isCFStringType(QualType T,ASTContext & Ctx)1787330f729Sjoerg static inline bool isCFStringType(QualType T, ASTContext &Ctx) {
1797330f729Sjoerg const auto *PT = T->getAs<PointerType>();
1807330f729Sjoerg if (!PT)
1817330f729Sjoerg return false;
1827330f729Sjoerg
1837330f729Sjoerg const auto *RT = PT->getPointeeType()->getAs<RecordType>();
1847330f729Sjoerg if (!RT)
1857330f729Sjoerg return false;
1867330f729Sjoerg
1877330f729Sjoerg const RecordDecl *RD = RT->getDecl();
1887330f729Sjoerg if (RD->getTagKind() != TTK_Struct)
1897330f729Sjoerg return false;
1907330f729Sjoerg
1917330f729Sjoerg return RD->getIdentifier() == &Ctx.Idents.get("__CFString");
1927330f729Sjoerg }
1937330f729Sjoerg
getNumAttributeArgs(const ParsedAttr & AL)1947330f729Sjoerg static unsigned getNumAttributeArgs(const ParsedAttr &AL) {
1957330f729Sjoerg // FIXME: Include the type in the argument list.
1967330f729Sjoerg return AL.getNumArgs() + AL.hasParsedType();
1977330f729Sjoerg }
1987330f729Sjoerg
1997330f729Sjoerg /// A helper function to provide Attribute Location for the Attr types
2007330f729Sjoerg /// AND the ParsedAttr.
2017330f729Sjoerg template <typename AttrInfo>
202*e038c9c4Sjoerg static std::enable_if_t<std::is_base_of<Attr, AttrInfo>::value, SourceLocation>
getAttrLoc(const AttrInfo & AL)2037330f729Sjoerg getAttrLoc(const AttrInfo &AL) {
2047330f729Sjoerg return AL.getLocation();
2057330f729Sjoerg }
getAttrLoc(const ParsedAttr & AL)2067330f729Sjoerg static SourceLocation getAttrLoc(const ParsedAttr &AL) { return AL.getLoc(); }
2077330f729Sjoerg
2087330f729Sjoerg /// If Expr is a valid integer constant, get the value of the integer
2097330f729Sjoerg /// expression and return success or failure. May output an error.
2107330f729Sjoerg ///
2117330f729Sjoerg /// Negative argument is implicitly converted to unsigned, unless
2127330f729Sjoerg /// \p StrictlyUnsigned is true.
2137330f729Sjoerg template <typename AttrInfo>
checkUInt32Argument(Sema & S,const AttrInfo & AI,const Expr * Expr,uint32_t & Val,unsigned Idx=UINT_MAX,bool StrictlyUnsigned=false)2147330f729Sjoerg static bool checkUInt32Argument(Sema &S, const AttrInfo &AI, const Expr *Expr,
2157330f729Sjoerg uint32_t &Val, unsigned Idx = UINT_MAX,
2167330f729Sjoerg bool StrictlyUnsigned = false) {
217*e038c9c4Sjoerg Optional<llvm::APSInt> I = llvm::APSInt(32);
2187330f729Sjoerg if (Expr->isTypeDependent() || Expr->isValueDependent() ||
219*e038c9c4Sjoerg !(I = Expr->getIntegerConstantExpr(S.Context))) {
2207330f729Sjoerg if (Idx != UINT_MAX)
2217330f729Sjoerg S.Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type)
2227330f729Sjoerg << &AI << Idx << AANT_ArgumentIntegerConstant
2237330f729Sjoerg << Expr->getSourceRange();
2247330f729Sjoerg else
2257330f729Sjoerg S.Diag(getAttrLoc(AI), diag::err_attribute_argument_type)
2267330f729Sjoerg << &AI << AANT_ArgumentIntegerConstant << Expr->getSourceRange();
2277330f729Sjoerg return false;
2287330f729Sjoerg }
2297330f729Sjoerg
230*e038c9c4Sjoerg if (!I->isIntN(32)) {
2317330f729Sjoerg S.Diag(Expr->getExprLoc(), diag::err_ice_too_large)
232*e038c9c4Sjoerg << I->toString(10, false) << 32 << /* Unsigned */ 1;
2337330f729Sjoerg return false;
2347330f729Sjoerg }
2357330f729Sjoerg
236*e038c9c4Sjoerg if (StrictlyUnsigned && I->isSigned() && I->isNegative()) {
2377330f729Sjoerg S.Diag(getAttrLoc(AI), diag::err_attribute_requires_positive_integer)
2387330f729Sjoerg << &AI << /*non-negative*/ 1;
2397330f729Sjoerg return false;
2407330f729Sjoerg }
2417330f729Sjoerg
242*e038c9c4Sjoerg Val = (uint32_t)I->getZExtValue();
2437330f729Sjoerg return true;
2447330f729Sjoerg }
2457330f729Sjoerg
2467330f729Sjoerg /// Wrapper around checkUInt32Argument, with an extra check to be sure
2477330f729Sjoerg /// that the result will fit into a regular (signed) int. All args have the same
2487330f729Sjoerg /// purpose as they do in checkUInt32Argument.
2497330f729Sjoerg template <typename AttrInfo>
checkPositiveIntArgument(Sema & S,const AttrInfo & AI,const Expr * Expr,int & Val,unsigned Idx=UINT_MAX)2507330f729Sjoerg static bool checkPositiveIntArgument(Sema &S, const AttrInfo &AI, const Expr *Expr,
2517330f729Sjoerg int &Val, unsigned Idx = UINT_MAX) {
2527330f729Sjoerg uint32_t UVal;
2537330f729Sjoerg if (!checkUInt32Argument(S, AI, Expr, UVal, Idx))
2547330f729Sjoerg return false;
2557330f729Sjoerg
2567330f729Sjoerg if (UVal > (uint32_t)std::numeric_limits<int>::max()) {
2577330f729Sjoerg llvm::APSInt I(32); // for toString
2587330f729Sjoerg I = UVal;
2597330f729Sjoerg S.Diag(Expr->getExprLoc(), diag::err_ice_too_large)
2607330f729Sjoerg << I.toString(10, false) << 32 << /* Unsigned */ 0;
2617330f729Sjoerg return false;
2627330f729Sjoerg }
2637330f729Sjoerg
2647330f729Sjoerg Val = UVal;
2657330f729Sjoerg return true;
2667330f729Sjoerg }
2677330f729Sjoerg
2687330f729Sjoerg /// Diagnose mutually exclusive attributes when present on a given
2697330f729Sjoerg /// declaration. Returns true if diagnosed.
2707330f729Sjoerg template <typename AttrTy>
checkAttrMutualExclusion(Sema & S,Decl * D,const ParsedAttr & AL)2717330f729Sjoerg static bool checkAttrMutualExclusion(Sema &S, Decl *D, const ParsedAttr &AL) {
2727330f729Sjoerg if (const auto *A = D->getAttr<AttrTy>()) {
2737330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) << AL << A;
2747330f729Sjoerg S.Diag(A->getLocation(), diag::note_conflicting_attribute);
2757330f729Sjoerg return true;
2767330f729Sjoerg }
2777330f729Sjoerg return false;
2787330f729Sjoerg }
2797330f729Sjoerg
2807330f729Sjoerg template <typename AttrTy>
checkAttrMutualExclusion(Sema & S,Decl * D,const Attr & AL)2817330f729Sjoerg static bool checkAttrMutualExclusion(Sema &S, Decl *D, const Attr &AL) {
2827330f729Sjoerg if (const auto *A = D->getAttr<AttrTy>()) {
2837330f729Sjoerg S.Diag(AL.getLocation(), diag::err_attributes_are_not_compatible) << &AL
2847330f729Sjoerg << A;
2857330f729Sjoerg S.Diag(A->getLocation(), diag::note_conflicting_attribute);
2867330f729Sjoerg return true;
2877330f729Sjoerg }
2887330f729Sjoerg return false;
2897330f729Sjoerg }
2907330f729Sjoerg
2917330f729Sjoerg /// Check if IdxExpr is a valid parameter index for a function or
2927330f729Sjoerg /// instance method D. May output an error.
2937330f729Sjoerg ///
2947330f729Sjoerg /// \returns true if IdxExpr is a valid index.
2957330f729Sjoerg template <typename AttrInfo>
checkFunctionOrMethodParameterIndex(Sema & S,const Decl * D,const AttrInfo & AI,unsigned AttrArgNum,const Expr * IdxExpr,ParamIdx & Idx,bool CanIndexImplicitThis=false)2967330f729Sjoerg static bool checkFunctionOrMethodParameterIndex(
2977330f729Sjoerg Sema &S, const Decl *D, const AttrInfo &AI, unsigned AttrArgNum,
2987330f729Sjoerg const Expr *IdxExpr, ParamIdx &Idx, bool CanIndexImplicitThis = false) {
2997330f729Sjoerg assert(isFunctionOrMethodOrBlock(D));
3007330f729Sjoerg
3017330f729Sjoerg // In C++ the implicit 'this' function parameter also counts.
3027330f729Sjoerg // Parameters are counted from one.
3037330f729Sjoerg bool HP = hasFunctionProto(D);
3047330f729Sjoerg bool HasImplicitThisParam = isInstanceMethod(D);
3057330f729Sjoerg bool IV = HP && isFunctionOrMethodVariadic(D);
3067330f729Sjoerg unsigned NumParams =
3077330f729Sjoerg (HP ? getFunctionOrMethodNumParams(D) : 0) + HasImplicitThisParam;
3087330f729Sjoerg
309*e038c9c4Sjoerg Optional<llvm::APSInt> IdxInt;
3107330f729Sjoerg if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() ||
311*e038c9c4Sjoerg !(IdxInt = IdxExpr->getIntegerConstantExpr(S.Context))) {
3127330f729Sjoerg S.Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type)
3137330f729Sjoerg << &AI << AttrArgNum << AANT_ArgumentIntegerConstant
3147330f729Sjoerg << IdxExpr->getSourceRange();
3157330f729Sjoerg return false;
3167330f729Sjoerg }
3177330f729Sjoerg
318*e038c9c4Sjoerg unsigned IdxSource = IdxInt->getLimitedValue(UINT_MAX);
3197330f729Sjoerg if (IdxSource < 1 || (!IV && IdxSource > NumParams)) {
3207330f729Sjoerg S.Diag(getAttrLoc(AI), diag::err_attribute_argument_out_of_bounds)
3217330f729Sjoerg << &AI << AttrArgNum << IdxExpr->getSourceRange();
3227330f729Sjoerg return false;
3237330f729Sjoerg }
3247330f729Sjoerg if (HasImplicitThisParam && !CanIndexImplicitThis) {
3257330f729Sjoerg if (IdxSource == 1) {
3267330f729Sjoerg S.Diag(getAttrLoc(AI), diag::err_attribute_invalid_implicit_this_argument)
3277330f729Sjoerg << &AI << IdxExpr->getSourceRange();
3287330f729Sjoerg return false;
3297330f729Sjoerg }
3307330f729Sjoerg }
3317330f729Sjoerg
3327330f729Sjoerg Idx = ParamIdx(IdxSource, D);
3337330f729Sjoerg return true;
3347330f729Sjoerg }
3357330f729Sjoerg
3367330f729Sjoerg /// Check if the argument \p ArgNum of \p Attr is a ASCII string literal.
3377330f729Sjoerg /// If not emit an error and return false. If the argument is an identifier it
3387330f729Sjoerg /// will emit an error with a fixit hint and treat it as if it was a string
3397330f729Sjoerg /// literal.
checkStringLiteralArgumentAttr(const ParsedAttr & AL,unsigned ArgNum,StringRef & Str,SourceLocation * ArgLocation)3407330f729Sjoerg bool Sema::checkStringLiteralArgumentAttr(const ParsedAttr &AL, unsigned ArgNum,
3417330f729Sjoerg StringRef &Str,
3427330f729Sjoerg SourceLocation *ArgLocation) {
3437330f729Sjoerg // Look for identifiers. If we have one emit a hint to fix it to a literal.
3447330f729Sjoerg if (AL.isArgIdent(ArgNum)) {
3457330f729Sjoerg IdentifierLoc *Loc = AL.getArgAsIdent(ArgNum);
3467330f729Sjoerg Diag(Loc->Loc, diag::err_attribute_argument_type)
3477330f729Sjoerg << AL << AANT_ArgumentString
3487330f729Sjoerg << FixItHint::CreateInsertion(Loc->Loc, "\"")
3497330f729Sjoerg << FixItHint::CreateInsertion(getLocForEndOfToken(Loc->Loc), "\"");
3507330f729Sjoerg Str = Loc->Ident->getName();
3517330f729Sjoerg if (ArgLocation)
3527330f729Sjoerg *ArgLocation = Loc->Loc;
3537330f729Sjoerg return true;
3547330f729Sjoerg }
3557330f729Sjoerg
3567330f729Sjoerg // Now check for an actual string literal.
3577330f729Sjoerg Expr *ArgExpr = AL.getArgAsExpr(ArgNum);
3587330f729Sjoerg const auto *Literal = dyn_cast<StringLiteral>(ArgExpr->IgnoreParenCasts());
3597330f729Sjoerg if (ArgLocation)
3607330f729Sjoerg *ArgLocation = ArgExpr->getBeginLoc();
3617330f729Sjoerg
3627330f729Sjoerg if (!Literal || !Literal->isAscii()) {
3637330f729Sjoerg Diag(ArgExpr->getBeginLoc(), diag::err_attribute_argument_type)
3647330f729Sjoerg << AL << AANT_ArgumentString;
3657330f729Sjoerg return false;
3667330f729Sjoerg }
3677330f729Sjoerg
3687330f729Sjoerg Str = Literal->getString();
3697330f729Sjoerg return true;
3707330f729Sjoerg }
3717330f729Sjoerg
3727330f729Sjoerg /// Applies the given attribute to the Decl without performing any
3737330f729Sjoerg /// additional semantic checking.
3747330f729Sjoerg template <typename AttrType>
handleSimpleAttribute(Sema & S,Decl * D,const AttributeCommonInfo & CI)3757330f729Sjoerg static void handleSimpleAttribute(Sema &S, Decl *D,
3767330f729Sjoerg const AttributeCommonInfo &CI) {
3777330f729Sjoerg D->addAttr(::new (S.Context) AttrType(S.Context, CI));
3787330f729Sjoerg }
3797330f729Sjoerg
3807330f729Sjoerg template <typename... DiagnosticArgs>
3817330f729Sjoerg static const Sema::SemaDiagnosticBuilder&
appendDiagnostics(const Sema::SemaDiagnosticBuilder & Bldr)3827330f729Sjoerg appendDiagnostics(const Sema::SemaDiagnosticBuilder &Bldr) {
3837330f729Sjoerg return Bldr;
3847330f729Sjoerg }
3857330f729Sjoerg
3867330f729Sjoerg template <typename T, typename... DiagnosticArgs>
3877330f729Sjoerg static const Sema::SemaDiagnosticBuilder&
appendDiagnostics(const Sema::SemaDiagnosticBuilder & Bldr,T && ExtraArg,DiagnosticArgs &&...ExtraArgs)3887330f729Sjoerg appendDiagnostics(const Sema::SemaDiagnosticBuilder &Bldr, T &&ExtraArg,
3897330f729Sjoerg DiagnosticArgs &&... ExtraArgs) {
3907330f729Sjoerg return appendDiagnostics(Bldr << std::forward<T>(ExtraArg),
3917330f729Sjoerg std::forward<DiagnosticArgs>(ExtraArgs)...);
3927330f729Sjoerg }
3937330f729Sjoerg
394*e038c9c4Sjoerg /// Add an attribute @c AttrType to declaration @c D, provided that
395*e038c9c4Sjoerg /// @c PassesCheck is true.
396*e038c9c4Sjoerg /// Otherwise, emit diagnostic @c DiagID, passing in all parameters
397*e038c9c4Sjoerg /// specified in @c ExtraArgs.
3987330f729Sjoerg template <typename AttrType, typename... DiagnosticArgs>
handleSimpleAttributeOrDiagnose(Sema & S,Decl * D,const AttributeCommonInfo & CI,bool PassesCheck,unsigned DiagID,DiagnosticArgs &&...ExtraArgs)3997330f729Sjoerg static void handleSimpleAttributeOrDiagnose(Sema &S, Decl *D,
4007330f729Sjoerg const AttributeCommonInfo &CI,
4017330f729Sjoerg bool PassesCheck, unsigned DiagID,
4027330f729Sjoerg DiagnosticArgs &&... ExtraArgs) {
4037330f729Sjoerg if (!PassesCheck) {
4047330f729Sjoerg Sema::SemaDiagnosticBuilder DB = S.Diag(D->getBeginLoc(), DiagID);
4057330f729Sjoerg appendDiagnostics(DB, std::forward<DiagnosticArgs>(ExtraArgs)...);
4067330f729Sjoerg return;
4077330f729Sjoerg }
4087330f729Sjoerg handleSimpleAttribute<AttrType>(S, D, CI);
4097330f729Sjoerg }
4107330f729Sjoerg
4117330f729Sjoerg /// Check if the passed-in expression is of type int or bool.
isIntOrBool(Expr * Exp)4127330f729Sjoerg static bool isIntOrBool(Expr *Exp) {
4137330f729Sjoerg QualType QT = Exp->getType();
4147330f729Sjoerg return QT->isBooleanType() || QT->isIntegerType();
4157330f729Sjoerg }
4167330f729Sjoerg
4177330f729Sjoerg
4187330f729Sjoerg // Check to see if the type is a smart pointer of some kind. We assume
4197330f729Sjoerg // it's a smart pointer if it defines both operator-> and operator*.
threadSafetyCheckIsSmartPointer(Sema & S,const RecordType * RT)4207330f729Sjoerg static bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordType* RT) {
4217330f729Sjoerg auto IsOverloadedOperatorPresent = [&S](const RecordDecl *Record,
4227330f729Sjoerg OverloadedOperatorKind Op) {
4237330f729Sjoerg DeclContextLookupResult Result =
4247330f729Sjoerg Record->lookup(S.Context.DeclarationNames.getCXXOperatorName(Op));
4257330f729Sjoerg return !Result.empty();
4267330f729Sjoerg };
4277330f729Sjoerg
4287330f729Sjoerg const RecordDecl *Record = RT->getDecl();
4297330f729Sjoerg bool foundStarOperator = IsOverloadedOperatorPresent(Record, OO_Star);
4307330f729Sjoerg bool foundArrowOperator = IsOverloadedOperatorPresent(Record, OO_Arrow);
4317330f729Sjoerg if (foundStarOperator && foundArrowOperator)
4327330f729Sjoerg return true;
4337330f729Sjoerg
4347330f729Sjoerg const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(Record);
4357330f729Sjoerg if (!CXXRecord)
4367330f729Sjoerg return false;
4377330f729Sjoerg
4387330f729Sjoerg for (auto BaseSpecifier : CXXRecord->bases()) {
4397330f729Sjoerg if (!foundStarOperator)
4407330f729Sjoerg foundStarOperator = IsOverloadedOperatorPresent(
4417330f729Sjoerg BaseSpecifier.getType()->getAsRecordDecl(), OO_Star);
4427330f729Sjoerg if (!foundArrowOperator)
4437330f729Sjoerg foundArrowOperator = IsOverloadedOperatorPresent(
4447330f729Sjoerg BaseSpecifier.getType()->getAsRecordDecl(), OO_Arrow);
4457330f729Sjoerg }
4467330f729Sjoerg
4477330f729Sjoerg if (foundStarOperator && foundArrowOperator)
4487330f729Sjoerg return true;
4497330f729Sjoerg
4507330f729Sjoerg return false;
4517330f729Sjoerg }
4527330f729Sjoerg
4537330f729Sjoerg /// Check if passed in Decl is a pointer type.
4547330f729Sjoerg /// Note that this function may produce an error message.
4557330f729Sjoerg /// \return true if the Decl is a pointer type; false otherwise
threadSafetyCheckIsPointer(Sema & S,const Decl * D,const ParsedAttr & AL)4567330f729Sjoerg static bool threadSafetyCheckIsPointer(Sema &S, const Decl *D,
4577330f729Sjoerg const ParsedAttr &AL) {
4587330f729Sjoerg const auto *VD = cast<ValueDecl>(D);
4597330f729Sjoerg QualType QT = VD->getType();
4607330f729Sjoerg if (QT->isAnyPointerType())
4617330f729Sjoerg return true;
4627330f729Sjoerg
4637330f729Sjoerg if (const auto *RT = QT->getAs<RecordType>()) {
4647330f729Sjoerg // If it's an incomplete type, it could be a smart pointer; skip it.
4657330f729Sjoerg // (We don't want to force template instantiation if we can avoid it,
4667330f729Sjoerg // since that would alter the order in which templates are instantiated.)
4677330f729Sjoerg if (RT->isIncompleteType())
4687330f729Sjoerg return true;
4697330f729Sjoerg
4707330f729Sjoerg if (threadSafetyCheckIsSmartPointer(S, RT))
4717330f729Sjoerg return true;
4727330f729Sjoerg }
4737330f729Sjoerg
4747330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_thread_attribute_decl_not_pointer) << AL << QT;
4757330f729Sjoerg return false;
4767330f729Sjoerg }
4777330f729Sjoerg
4787330f729Sjoerg /// Checks that the passed in QualType either is of RecordType or points
4797330f729Sjoerg /// to RecordType. Returns the relevant RecordType, null if it does not exit.
getRecordType(QualType QT)4807330f729Sjoerg static const RecordType *getRecordType(QualType QT) {
4817330f729Sjoerg if (const auto *RT = QT->getAs<RecordType>())
4827330f729Sjoerg return RT;
4837330f729Sjoerg
4847330f729Sjoerg // Now check if we point to record type.
4857330f729Sjoerg if (const auto *PT = QT->getAs<PointerType>())
4867330f729Sjoerg return PT->getPointeeType()->getAs<RecordType>();
4877330f729Sjoerg
4887330f729Sjoerg return nullptr;
4897330f729Sjoerg }
4907330f729Sjoerg
4917330f729Sjoerg template <typename AttrType>
checkRecordDeclForAttr(const RecordDecl * RD)4927330f729Sjoerg static bool checkRecordDeclForAttr(const RecordDecl *RD) {
4937330f729Sjoerg // Check if the record itself has the attribute.
4947330f729Sjoerg if (RD->hasAttr<AttrType>())
4957330f729Sjoerg return true;
4967330f729Sjoerg
4977330f729Sjoerg // Else check if any base classes have the attribute.
4987330f729Sjoerg if (const auto *CRD = dyn_cast<CXXRecordDecl>(RD)) {
499*e038c9c4Sjoerg if (!CRD->forallBases([](const CXXRecordDecl *Base) {
500*e038c9c4Sjoerg return !Base->hasAttr<AttrType>();
501*e038c9c4Sjoerg }))
5027330f729Sjoerg return true;
5037330f729Sjoerg }
5047330f729Sjoerg return false;
5057330f729Sjoerg }
5067330f729Sjoerg
checkRecordTypeForCapability(Sema & S,QualType Ty)5077330f729Sjoerg static bool checkRecordTypeForCapability(Sema &S, QualType Ty) {
5087330f729Sjoerg const RecordType *RT = getRecordType(Ty);
5097330f729Sjoerg
5107330f729Sjoerg if (!RT)
5117330f729Sjoerg return false;
5127330f729Sjoerg
5137330f729Sjoerg // Don't check for the capability if the class hasn't been defined yet.
5147330f729Sjoerg if (RT->isIncompleteType())
5157330f729Sjoerg return true;
5167330f729Sjoerg
5177330f729Sjoerg // Allow smart pointers to be used as capability objects.
5187330f729Sjoerg // FIXME -- Check the type that the smart pointer points to.
5197330f729Sjoerg if (threadSafetyCheckIsSmartPointer(S, RT))
5207330f729Sjoerg return true;
5217330f729Sjoerg
5227330f729Sjoerg return checkRecordDeclForAttr<CapabilityAttr>(RT->getDecl());
5237330f729Sjoerg }
5247330f729Sjoerg
checkTypedefTypeForCapability(QualType Ty)5257330f729Sjoerg static bool checkTypedefTypeForCapability(QualType Ty) {
5267330f729Sjoerg const auto *TD = Ty->getAs<TypedefType>();
5277330f729Sjoerg if (!TD)
5287330f729Sjoerg return false;
5297330f729Sjoerg
5307330f729Sjoerg TypedefNameDecl *TN = TD->getDecl();
5317330f729Sjoerg if (!TN)
5327330f729Sjoerg return false;
5337330f729Sjoerg
5347330f729Sjoerg return TN->hasAttr<CapabilityAttr>();
5357330f729Sjoerg }
5367330f729Sjoerg
typeHasCapability(Sema & S,QualType Ty)5377330f729Sjoerg static bool typeHasCapability(Sema &S, QualType Ty) {
5387330f729Sjoerg if (checkTypedefTypeForCapability(Ty))
5397330f729Sjoerg return true;
5407330f729Sjoerg
5417330f729Sjoerg if (checkRecordTypeForCapability(S, Ty))
5427330f729Sjoerg return true;
5437330f729Sjoerg
5447330f729Sjoerg return false;
5457330f729Sjoerg }
5467330f729Sjoerg
isCapabilityExpr(Sema & S,const Expr * Ex)5477330f729Sjoerg static bool isCapabilityExpr(Sema &S, const Expr *Ex) {
5487330f729Sjoerg // Capability expressions are simple expressions involving the boolean logic
5497330f729Sjoerg // operators &&, || or !, a simple DeclRefExpr, CastExpr or a ParenExpr. Once
5507330f729Sjoerg // a DeclRefExpr is found, its type should be checked to determine whether it
5517330f729Sjoerg // is a capability or not.
5527330f729Sjoerg
5537330f729Sjoerg if (const auto *E = dyn_cast<CastExpr>(Ex))
5547330f729Sjoerg return isCapabilityExpr(S, E->getSubExpr());
5557330f729Sjoerg else if (const auto *E = dyn_cast<ParenExpr>(Ex))
5567330f729Sjoerg return isCapabilityExpr(S, E->getSubExpr());
5577330f729Sjoerg else if (const auto *E = dyn_cast<UnaryOperator>(Ex)) {
5587330f729Sjoerg if (E->getOpcode() == UO_LNot || E->getOpcode() == UO_AddrOf ||
5597330f729Sjoerg E->getOpcode() == UO_Deref)
5607330f729Sjoerg return isCapabilityExpr(S, E->getSubExpr());
5617330f729Sjoerg return false;
5627330f729Sjoerg } else if (const auto *E = dyn_cast<BinaryOperator>(Ex)) {
5637330f729Sjoerg if (E->getOpcode() == BO_LAnd || E->getOpcode() == BO_LOr)
5647330f729Sjoerg return isCapabilityExpr(S, E->getLHS()) &&
5657330f729Sjoerg isCapabilityExpr(S, E->getRHS());
5667330f729Sjoerg return false;
5677330f729Sjoerg }
5687330f729Sjoerg
5697330f729Sjoerg return typeHasCapability(S, Ex->getType());
5707330f729Sjoerg }
5717330f729Sjoerg
5727330f729Sjoerg /// Checks that all attribute arguments, starting from Sidx, resolve to
5737330f729Sjoerg /// a capability object.
5747330f729Sjoerg /// \param Sidx The attribute argument index to start checking with.
5757330f729Sjoerg /// \param ParamIdxOk Whether an argument can be indexing into a function
5767330f729Sjoerg /// parameter list.
checkAttrArgsAreCapabilityObjs(Sema & S,Decl * D,const ParsedAttr & AL,SmallVectorImpl<Expr * > & Args,unsigned Sidx=0,bool ParamIdxOk=false)5777330f729Sjoerg static void checkAttrArgsAreCapabilityObjs(Sema &S, Decl *D,
5787330f729Sjoerg const ParsedAttr &AL,
5797330f729Sjoerg SmallVectorImpl<Expr *> &Args,
5807330f729Sjoerg unsigned Sidx = 0,
5817330f729Sjoerg bool ParamIdxOk = false) {
5827330f729Sjoerg if (Sidx == AL.getNumArgs()) {
5837330f729Sjoerg // If we don't have any capability arguments, the attribute implicitly
5847330f729Sjoerg // refers to 'this'. So we need to make sure that 'this' exists, i.e. we're
5857330f729Sjoerg // a non-static method, and that the class is a (scoped) capability.
5867330f729Sjoerg const auto *MD = dyn_cast<const CXXMethodDecl>(D);
5877330f729Sjoerg if (MD && !MD->isStatic()) {
5887330f729Sjoerg const CXXRecordDecl *RD = MD->getParent();
5897330f729Sjoerg // FIXME -- need to check this again on template instantiation
5907330f729Sjoerg if (!checkRecordDeclForAttr<CapabilityAttr>(RD) &&
5917330f729Sjoerg !checkRecordDeclForAttr<ScopedLockableAttr>(RD))
5927330f729Sjoerg S.Diag(AL.getLoc(),
5937330f729Sjoerg diag::warn_thread_attribute_not_on_capability_member)
5947330f729Sjoerg << AL << MD->getParent();
5957330f729Sjoerg } else {
5967330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_thread_attribute_not_on_non_static_member)
5977330f729Sjoerg << AL;
5987330f729Sjoerg }
5997330f729Sjoerg }
6007330f729Sjoerg
6017330f729Sjoerg for (unsigned Idx = Sidx; Idx < AL.getNumArgs(); ++Idx) {
6027330f729Sjoerg Expr *ArgExp = AL.getArgAsExpr(Idx);
6037330f729Sjoerg
6047330f729Sjoerg if (ArgExp->isTypeDependent()) {
6057330f729Sjoerg // FIXME -- need to check this again on template instantiation
6067330f729Sjoerg Args.push_back(ArgExp);
6077330f729Sjoerg continue;
6087330f729Sjoerg }
6097330f729Sjoerg
6107330f729Sjoerg if (const auto *StrLit = dyn_cast<StringLiteral>(ArgExp)) {
6117330f729Sjoerg if (StrLit->getLength() == 0 ||
6127330f729Sjoerg (StrLit->isAscii() && StrLit->getString() == StringRef("*"))) {
6137330f729Sjoerg // Pass empty strings to the analyzer without warnings.
6147330f729Sjoerg // Treat "*" as the universal lock.
6157330f729Sjoerg Args.push_back(ArgExp);
6167330f729Sjoerg continue;
6177330f729Sjoerg }
6187330f729Sjoerg
6197330f729Sjoerg // We allow constant strings to be used as a placeholder for expressions
6207330f729Sjoerg // that are not valid C++ syntax, but warn that they are ignored.
6217330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_thread_attribute_ignored) << AL;
6227330f729Sjoerg Args.push_back(ArgExp);
6237330f729Sjoerg continue;
6247330f729Sjoerg }
6257330f729Sjoerg
6267330f729Sjoerg QualType ArgTy = ArgExp->getType();
6277330f729Sjoerg
6287330f729Sjoerg // A pointer to member expression of the form &MyClass::mu is treated
6297330f729Sjoerg // specially -- we need to look at the type of the member.
6307330f729Sjoerg if (const auto *UOp = dyn_cast<UnaryOperator>(ArgExp))
6317330f729Sjoerg if (UOp->getOpcode() == UO_AddrOf)
6327330f729Sjoerg if (const auto *DRE = dyn_cast<DeclRefExpr>(UOp->getSubExpr()))
6337330f729Sjoerg if (DRE->getDecl()->isCXXInstanceMember())
6347330f729Sjoerg ArgTy = DRE->getDecl()->getType();
6357330f729Sjoerg
6367330f729Sjoerg // First see if we can just cast to record type, or pointer to record type.
6377330f729Sjoerg const RecordType *RT = getRecordType(ArgTy);
6387330f729Sjoerg
6397330f729Sjoerg // Now check if we index into a record type function param.
6407330f729Sjoerg if(!RT && ParamIdxOk) {
6417330f729Sjoerg const auto *FD = dyn_cast<FunctionDecl>(D);
6427330f729Sjoerg const auto *IL = dyn_cast<IntegerLiteral>(ArgExp);
6437330f729Sjoerg if(FD && IL) {
6447330f729Sjoerg unsigned int NumParams = FD->getNumParams();
6457330f729Sjoerg llvm::APInt ArgValue = IL->getValue();
6467330f729Sjoerg uint64_t ParamIdxFromOne = ArgValue.getZExtValue();
6477330f729Sjoerg uint64_t ParamIdxFromZero = ParamIdxFromOne - 1;
6487330f729Sjoerg if (!ArgValue.isStrictlyPositive() || ParamIdxFromOne > NumParams) {
6497330f729Sjoerg S.Diag(AL.getLoc(),
6507330f729Sjoerg diag::err_attribute_argument_out_of_bounds_extra_info)
6517330f729Sjoerg << AL << Idx + 1 << NumParams;
6527330f729Sjoerg continue;
6537330f729Sjoerg }
6547330f729Sjoerg ArgTy = FD->getParamDecl(ParamIdxFromZero)->getType();
6557330f729Sjoerg }
6567330f729Sjoerg }
6577330f729Sjoerg
6587330f729Sjoerg // If the type does not have a capability, see if the components of the
6597330f729Sjoerg // expression have capabilities. This allows for writing C code where the
6607330f729Sjoerg // capability may be on the type, and the expression is a capability
6617330f729Sjoerg // boolean logic expression. Eg) requires_capability(A || B && !C)
6627330f729Sjoerg if (!typeHasCapability(S, ArgTy) && !isCapabilityExpr(S, ArgExp))
6637330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_thread_attribute_argument_not_lockable)
6647330f729Sjoerg << AL << ArgTy;
6657330f729Sjoerg
6667330f729Sjoerg Args.push_back(ArgExp);
6677330f729Sjoerg }
6687330f729Sjoerg }
6697330f729Sjoerg
6707330f729Sjoerg //===----------------------------------------------------------------------===//
6717330f729Sjoerg // Attribute Implementations
6727330f729Sjoerg //===----------------------------------------------------------------------===//
6737330f729Sjoerg
handlePtGuardedVarAttr(Sema & S,Decl * D,const ParsedAttr & AL)6747330f729Sjoerg static void handlePtGuardedVarAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
6757330f729Sjoerg if (!threadSafetyCheckIsPointer(S, D, AL))
6767330f729Sjoerg return;
6777330f729Sjoerg
6787330f729Sjoerg D->addAttr(::new (S.Context) PtGuardedVarAttr(S.Context, AL));
6797330f729Sjoerg }
6807330f729Sjoerg
checkGuardedByAttrCommon(Sema & S,Decl * D,const ParsedAttr & AL,Expr * & Arg)6817330f729Sjoerg static bool checkGuardedByAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL,
6827330f729Sjoerg Expr *&Arg) {
6837330f729Sjoerg SmallVector<Expr *, 1> Args;
6847330f729Sjoerg // check that all arguments are lockable objects
6857330f729Sjoerg checkAttrArgsAreCapabilityObjs(S, D, AL, Args);
6867330f729Sjoerg unsigned Size = Args.size();
6877330f729Sjoerg if (Size != 1)
6887330f729Sjoerg return false;
6897330f729Sjoerg
6907330f729Sjoerg Arg = Args[0];
6917330f729Sjoerg
6927330f729Sjoerg return true;
6937330f729Sjoerg }
6947330f729Sjoerg
handleGuardedByAttr(Sema & S,Decl * D,const ParsedAttr & AL)6957330f729Sjoerg static void handleGuardedByAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
6967330f729Sjoerg Expr *Arg = nullptr;
6977330f729Sjoerg if (!checkGuardedByAttrCommon(S, D, AL, Arg))
6987330f729Sjoerg return;
6997330f729Sjoerg
7007330f729Sjoerg D->addAttr(::new (S.Context) GuardedByAttr(S.Context, AL, Arg));
7017330f729Sjoerg }
7027330f729Sjoerg
handlePtGuardedByAttr(Sema & S,Decl * D,const ParsedAttr & AL)7037330f729Sjoerg static void handlePtGuardedByAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
7047330f729Sjoerg Expr *Arg = nullptr;
7057330f729Sjoerg if (!checkGuardedByAttrCommon(S, D, AL, Arg))
7067330f729Sjoerg return;
7077330f729Sjoerg
7087330f729Sjoerg if (!threadSafetyCheckIsPointer(S, D, AL))
7097330f729Sjoerg return;
7107330f729Sjoerg
7117330f729Sjoerg D->addAttr(::new (S.Context) PtGuardedByAttr(S.Context, AL, Arg));
7127330f729Sjoerg }
7137330f729Sjoerg
checkAcquireOrderAttrCommon(Sema & S,Decl * D,const ParsedAttr & AL,SmallVectorImpl<Expr * > & Args)7147330f729Sjoerg static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL,
7157330f729Sjoerg SmallVectorImpl<Expr *> &Args) {
716*e038c9c4Sjoerg if (!AL.checkAtLeastNumArgs(S, 1))
7177330f729Sjoerg return false;
7187330f729Sjoerg
7197330f729Sjoerg // Check that this attribute only applies to lockable types.
7207330f729Sjoerg QualType QT = cast<ValueDecl>(D)->getType();
7217330f729Sjoerg if (!QT->isDependentType() && !typeHasCapability(S, QT)) {
7227330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_thread_attribute_decl_not_lockable) << AL;
7237330f729Sjoerg return false;
7247330f729Sjoerg }
7257330f729Sjoerg
7267330f729Sjoerg // Check that all arguments are lockable objects.
7277330f729Sjoerg checkAttrArgsAreCapabilityObjs(S, D, AL, Args);
7287330f729Sjoerg if (Args.empty())
7297330f729Sjoerg return false;
7307330f729Sjoerg
7317330f729Sjoerg return true;
7327330f729Sjoerg }
7337330f729Sjoerg
handleAcquiredAfterAttr(Sema & S,Decl * D,const ParsedAttr & AL)7347330f729Sjoerg static void handleAcquiredAfterAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
7357330f729Sjoerg SmallVector<Expr *, 1> Args;
7367330f729Sjoerg if (!checkAcquireOrderAttrCommon(S, D, AL, Args))
7377330f729Sjoerg return;
7387330f729Sjoerg
7397330f729Sjoerg Expr **StartArg = &Args[0];
7407330f729Sjoerg D->addAttr(::new (S.Context)
7417330f729Sjoerg AcquiredAfterAttr(S.Context, AL, StartArg, Args.size()));
7427330f729Sjoerg }
7437330f729Sjoerg
handleAcquiredBeforeAttr(Sema & S,Decl * D,const ParsedAttr & AL)7447330f729Sjoerg static void handleAcquiredBeforeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
7457330f729Sjoerg SmallVector<Expr *, 1> Args;
7467330f729Sjoerg if (!checkAcquireOrderAttrCommon(S, D, AL, Args))
7477330f729Sjoerg return;
7487330f729Sjoerg
7497330f729Sjoerg Expr **StartArg = &Args[0];
7507330f729Sjoerg D->addAttr(::new (S.Context)
7517330f729Sjoerg AcquiredBeforeAttr(S.Context, AL, StartArg, Args.size()));
7527330f729Sjoerg }
7537330f729Sjoerg
checkLockFunAttrCommon(Sema & S,Decl * D,const ParsedAttr & AL,SmallVectorImpl<Expr * > & Args)7547330f729Sjoerg static bool checkLockFunAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL,
7557330f729Sjoerg SmallVectorImpl<Expr *> &Args) {
7567330f729Sjoerg // zero or more arguments ok
7577330f729Sjoerg // check that all arguments are lockable objects
7587330f729Sjoerg checkAttrArgsAreCapabilityObjs(S, D, AL, Args, 0, /*ParamIdxOk=*/true);
7597330f729Sjoerg
7607330f729Sjoerg return true;
7617330f729Sjoerg }
7627330f729Sjoerg
handleAssertSharedLockAttr(Sema & S,Decl * D,const ParsedAttr & AL)7637330f729Sjoerg static void handleAssertSharedLockAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
7647330f729Sjoerg SmallVector<Expr *, 1> Args;
7657330f729Sjoerg if (!checkLockFunAttrCommon(S, D, AL, Args))
7667330f729Sjoerg return;
7677330f729Sjoerg
7687330f729Sjoerg unsigned Size = Args.size();
7697330f729Sjoerg Expr **StartArg = Size == 0 ? nullptr : &Args[0];
7707330f729Sjoerg D->addAttr(::new (S.Context)
7717330f729Sjoerg AssertSharedLockAttr(S.Context, AL, StartArg, Size));
7727330f729Sjoerg }
7737330f729Sjoerg
handleAssertExclusiveLockAttr(Sema & S,Decl * D,const ParsedAttr & AL)7747330f729Sjoerg static void handleAssertExclusiveLockAttr(Sema &S, Decl *D,
7757330f729Sjoerg const ParsedAttr &AL) {
7767330f729Sjoerg SmallVector<Expr *, 1> Args;
7777330f729Sjoerg if (!checkLockFunAttrCommon(S, D, AL, Args))
7787330f729Sjoerg return;
7797330f729Sjoerg
7807330f729Sjoerg unsigned Size = Args.size();
7817330f729Sjoerg Expr **StartArg = Size == 0 ? nullptr : &Args[0];
7827330f729Sjoerg D->addAttr(::new (S.Context)
7837330f729Sjoerg AssertExclusiveLockAttr(S.Context, AL, StartArg, Size));
7847330f729Sjoerg }
7857330f729Sjoerg
7867330f729Sjoerg /// Checks to be sure that the given parameter number is in bounds, and
7877330f729Sjoerg /// is an integral type. Will emit appropriate diagnostics if this returns
7887330f729Sjoerg /// false.
7897330f729Sjoerg ///
7907330f729Sjoerg /// AttrArgNo is used to actually retrieve the argument, so it's base-0.
7917330f729Sjoerg template <typename AttrInfo>
checkParamIsIntegerType(Sema & S,const Decl * D,const AttrInfo & AI,unsigned AttrArgNo)792*e038c9c4Sjoerg static bool checkParamIsIntegerType(Sema &S, const Decl *D, const AttrInfo &AI,
793*e038c9c4Sjoerg unsigned AttrArgNo) {
7947330f729Sjoerg assert(AI.isArgExpr(AttrArgNo) && "Expected expression argument");
7957330f729Sjoerg Expr *AttrArg = AI.getArgAsExpr(AttrArgNo);
7967330f729Sjoerg ParamIdx Idx;
797*e038c9c4Sjoerg if (!checkFunctionOrMethodParameterIndex(S, D, AI, AttrArgNo + 1, AttrArg,
7987330f729Sjoerg Idx))
7997330f729Sjoerg return false;
8007330f729Sjoerg
801*e038c9c4Sjoerg QualType ParamTy = getFunctionOrMethodParamType(D, Idx.getASTIndex());
802*e038c9c4Sjoerg if (!ParamTy->isIntegerType() && !ParamTy->isCharType()) {
8037330f729Sjoerg SourceLocation SrcLoc = AttrArg->getBeginLoc();
8047330f729Sjoerg S.Diag(SrcLoc, diag::err_attribute_integers_only)
805*e038c9c4Sjoerg << AI << getFunctionOrMethodParamRange(D, Idx.getASTIndex());
8067330f729Sjoerg return false;
8077330f729Sjoerg }
8087330f729Sjoerg return true;
8097330f729Sjoerg }
8107330f729Sjoerg
handleAllocSizeAttr(Sema & S,Decl * D,const ParsedAttr & AL)8117330f729Sjoerg static void handleAllocSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
812*e038c9c4Sjoerg if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 2))
8137330f729Sjoerg return;
8147330f729Sjoerg
815*e038c9c4Sjoerg assert(isFunctionOrMethod(D) && hasFunctionProto(D));
816*e038c9c4Sjoerg
817*e038c9c4Sjoerg QualType RetTy = getFunctionOrMethodResultType(D);
818*e038c9c4Sjoerg if (!RetTy->isPointerType()) {
8197330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only) << AL;
8207330f729Sjoerg return;
8217330f729Sjoerg }
8227330f729Sjoerg
8237330f729Sjoerg const Expr *SizeExpr = AL.getArgAsExpr(0);
8247330f729Sjoerg int SizeArgNoVal;
8257330f729Sjoerg // Parameter indices are 1-indexed, hence Index=1
8267330f729Sjoerg if (!checkPositiveIntArgument(S, AL, SizeExpr, SizeArgNoVal, /*Idx=*/1))
8277330f729Sjoerg return;
828*e038c9c4Sjoerg if (!checkParamIsIntegerType(S, D, AL, /*AttrArgNo=*/0))
8297330f729Sjoerg return;
8307330f729Sjoerg ParamIdx SizeArgNo(SizeArgNoVal, D);
8317330f729Sjoerg
8327330f729Sjoerg ParamIdx NumberArgNo;
8337330f729Sjoerg if (AL.getNumArgs() == 2) {
8347330f729Sjoerg const Expr *NumberExpr = AL.getArgAsExpr(1);
8357330f729Sjoerg int Val;
8367330f729Sjoerg // Parameter indices are 1-based, hence Index=2
8377330f729Sjoerg if (!checkPositiveIntArgument(S, AL, NumberExpr, Val, /*Idx=*/2))
8387330f729Sjoerg return;
839*e038c9c4Sjoerg if (!checkParamIsIntegerType(S, D, AL, /*AttrArgNo=*/1))
8407330f729Sjoerg return;
8417330f729Sjoerg NumberArgNo = ParamIdx(Val, D);
8427330f729Sjoerg }
8437330f729Sjoerg
8447330f729Sjoerg D->addAttr(::new (S.Context)
8457330f729Sjoerg AllocSizeAttr(S.Context, AL, SizeArgNo, NumberArgNo));
8467330f729Sjoerg }
8477330f729Sjoerg
checkTryLockFunAttrCommon(Sema & S,Decl * D,const ParsedAttr & AL,SmallVectorImpl<Expr * > & Args)8487330f729Sjoerg static bool checkTryLockFunAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL,
8497330f729Sjoerg SmallVectorImpl<Expr *> &Args) {
850*e038c9c4Sjoerg if (!AL.checkAtLeastNumArgs(S, 1))
8517330f729Sjoerg return false;
8527330f729Sjoerg
8537330f729Sjoerg if (!isIntOrBool(AL.getArgAsExpr(0))) {
8547330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
8557330f729Sjoerg << AL << 1 << AANT_ArgumentIntOrBool;
8567330f729Sjoerg return false;
8577330f729Sjoerg }
8587330f729Sjoerg
8597330f729Sjoerg // check that all arguments are lockable objects
8607330f729Sjoerg checkAttrArgsAreCapabilityObjs(S, D, AL, Args, 1);
8617330f729Sjoerg
8627330f729Sjoerg return true;
8637330f729Sjoerg }
8647330f729Sjoerg
handleSharedTrylockFunctionAttr(Sema & S,Decl * D,const ParsedAttr & AL)8657330f729Sjoerg static void handleSharedTrylockFunctionAttr(Sema &S, Decl *D,
8667330f729Sjoerg const ParsedAttr &AL) {
8677330f729Sjoerg SmallVector<Expr*, 2> Args;
8687330f729Sjoerg if (!checkTryLockFunAttrCommon(S, D, AL, Args))
8697330f729Sjoerg return;
8707330f729Sjoerg
8717330f729Sjoerg D->addAttr(::new (S.Context) SharedTrylockFunctionAttr(
8727330f729Sjoerg S.Context, AL, AL.getArgAsExpr(0), Args.data(), Args.size()));
8737330f729Sjoerg }
8747330f729Sjoerg
handleExclusiveTrylockFunctionAttr(Sema & S,Decl * D,const ParsedAttr & AL)8757330f729Sjoerg static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D,
8767330f729Sjoerg const ParsedAttr &AL) {
8777330f729Sjoerg SmallVector<Expr*, 2> Args;
8787330f729Sjoerg if (!checkTryLockFunAttrCommon(S, D, AL, Args))
8797330f729Sjoerg return;
8807330f729Sjoerg
8817330f729Sjoerg D->addAttr(::new (S.Context) ExclusiveTrylockFunctionAttr(
8827330f729Sjoerg S.Context, AL, AL.getArgAsExpr(0), Args.data(), Args.size()));
8837330f729Sjoerg }
8847330f729Sjoerg
handleLockReturnedAttr(Sema & S,Decl * D,const ParsedAttr & AL)8857330f729Sjoerg static void handleLockReturnedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
8867330f729Sjoerg // check that the argument is lockable object
8877330f729Sjoerg SmallVector<Expr*, 1> Args;
8887330f729Sjoerg checkAttrArgsAreCapabilityObjs(S, D, AL, Args);
8897330f729Sjoerg unsigned Size = Args.size();
8907330f729Sjoerg if (Size == 0)
8917330f729Sjoerg return;
8927330f729Sjoerg
8937330f729Sjoerg D->addAttr(::new (S.Context) LockReturnedAttr(S.Context, AL, Args[0]));
8947330f729Sjoerg }
8957330f729Sjoerg
handleLocksExcludedAttr(Sema & S,Decl * D,const ParsedAttr & AL)8967330f729Sjoerg static void handleLocksExcludedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
897*e038c9c4Sjoerg if (!AL.checkAtLeastNumArgs(S, 1))
8987330f729Sjoerg return;
8997330f729Sjoerg
9007330f729Sjoerg // check that all arguments are lockable objects
9017330f729Sjoerg SmallVector<Expr*, 1> Args;
9027330f729Sjoerg checkAttrArgsAreCapabilityObjs(S, D, AL, Args);
9037330f729Sjoerg unsigned Size = Args.size();
9047330f729Sjoerg if (Size == 0)
9057330f729Sjoerg return;
9067330f729Sjoerg Expr **StartArg = &Args[0];
9077330f729Sjoerg
9087330f729Sjoerg D->addAttr(::new (S.Context)
9097330f729Sjoerg LocksExcludedAttr(S.Context, AL, StartArg, Size));
9107330f729Sjoerg }
9117330f729Sjoerg
checkFunctionConditionAttr(Sema & S,Decl * D,const ParsedAttr & AL,Expr * & Cond,StringRef & Msg)9127330f729Sjoerg static bool checkFunctionConditionAttr(Sema &S, Decl *D, const ParsedAttr &AL,
9137330f729Sjoerg Expr *&Cond, StringRef &Msg) {
9147330f729Sjoerg Cond = AL.getArgAsExpr(0);
9157330f729Sjoerg if (!Cond->isTypeDependent()) {
9167330f729Sjoerg ExprResult Converted = S.PerformContextuallyConvertToBool(Cond);
9177330f729Sjoerg if (Converted.isInvalid())
9187330f729Sjoerg return false;
9197330f729Sjoerg Cond = Converted.get();
9207330f729Sjoerg }
9217330f729Sjoerg
9227330f729Sjoerg if (!S.checkStringLiteralArgumentAttr(AL, 1, Msg))
9237330f729Sjoerg return false;
9247330f729Sjoerg
9257330f729Sjoerg if (Msg.empty())
9267330f729Sjoerg Msg = "<no message provided>";
9277330f729Sjoerg
9287330f729Sjoerg SmallVector<PartialDiagnosticAt, 8> Diags;
9297330f729Sjoerg if (isa<FunctionDecl>(D) && !Cond->isValueDependent() &&
9307330f729Sjoerg !Expr::isPotentialConstantExprUnevaluated(Cond, cast<FunctionDecl>(D),
9317330f729Sjoerg Diags)) {
9327330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attr_cond_never_constant_expr) << AL;
9337330f729Sjoerg for (const PartialDiagnosticAt &PDiag : Diags)
9347330f729Sjoerg S.Diag(PDiag.first, PDiag.second);
9357330f729Sjoerg return false;
9367330f729Sjoerg }
9377330f729Sjoerg return true;
9387330f729Sjoerg }
9397330f729Sjoerg
handleEnableIfAttr(Sema & S,Decl * D,const ParsedAttr & AL)9407330f729Sjoerg static void handleEnableIfAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
9417330f729Sjoerg S.Diag(AL.getLoc(), diag::ext_clang_enable_if);
9427330f729Sjoerg
9437330f729Sjoerg Expr *Cond;
9447330f729Sjoerg StringRef Msg;
9457330f729Sjoerg if (checkFunctionConditionAttr(S, D, AL, Cond, Msg))
9467330f729Sjoerg D->addAttr(::new (S.Context) EnableIfAttr(S.Context, AL, Cond, Msg));
9477330f729Sjoerg }
9487330f729Sjoerg
9497330f729Sjoerg namespace {
9507330f729Sjoerg /// Determines if a given Expr references any of the given function's
9517330f729Sjoerg /// ParmVarDecls, or the function's implicit `this` parameter (if applicable).
9527330f729Sjoerg class ArgumentDependenceChecker
9537330f729Sjoerg : public RecursiveASTVisitor<ArgumentDependenceChecker> {
9547330f729Sjoerg #ifndef NDEBUG
9557330f729Sjoerg const CXXRecordDecl *ClassType;
9567330f729Sjoerg #endif
9577330f729Sjoerg llvm::SmallPtrSet<const ParmVarDecl *, 16> Parms;
9587330f729Sjoerg bool Result;
9597330f729Sjoerg
9607330f729Sjoerg public:
ArgumentDependenceChecker(const FunctionDecl * FD)9617330f729Sjoerg ArgumentDependenceChecker(const FunctionDecl *FD) {
9627330f729Sjoerg #ifndef NDEBUG
9637330f729Sjoerg if (const auto *MD = dyn_cast<CXXMethodDecl>(FD))
9647330f729Sjoerg ClassType = MD->getParent();
9657330f729Sjoerg else
9667330f729Sjoerg ClassType = nullptr;
9677330f729Sjoerg #endif
9687330f729Sjoerg Parms.insert(FD->param_begin(), FD->param_end());
9697330f729Sjoerg }
9707330f729Sjoerg
referencesArgs(Expr * E)9717330f729Sjoerg bool referencesArgs(Expr *E) {
9727330f729Sjoerg Result = false;
9737330f729Sjoerg TraverseStmt(E);
9747330f729Sjoerg return Result;
9757330f729Sjoerg }
9767330f729Sjoerg
VisitCXXThisExpr(CXXThisExpr * E)9777330f729Sjoerg bool VisitCXXThisExpr(CXXThisExpr *E) {
9787330f729Sjoerg assert(E->getType()->getPointeeCXXRecordDecl() == ClassType &&
9797330f729Sjoerg "`this` doesn't refer to the enclosing class?");
9807330f729Sjoerg Result = true;
9817330f729Sjoerg return false;
9827330f729Sjoerg }
9837330f729Sjoerg
VisitDeclRefExpr(DeclRefExpr * DRE)9847330f729Sjoerg bool VisitDeclRefExpr(DeclRefExpr *DRE) {
9857330f729Sjoerg if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
9867330f729Sjoerg if (Parms.count(PVD)) {
9877330f729Sjoerg Result = true;
9887330f729Sjoerg return false;
9897330f729Sjoerg }
9907330f729Sjoerg return true;
9917330f729Sjoerg }
9927330f729Sjoerg };
9937330f729Sjoerg }
9947330f729Sjoerg
handleDiagnoseIfAttr(Sema & S,Decl * D,const ParsedAttr & AL)9957330f729Sjoerg static void handleDiagnoseIfAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
9967330f729Sjoerg S.Diag(AL.getLoc(), diag::ext_clang_diagnose_if);
9977330f729Sjoerg
9987330f729Sjoerg Expr *Cond;
9997330f729Sjoerg StringRef Msg;
10007330f729Sjoerg if (!checkFunctionConditionAttr(S, D, AL, Cond, Msg))
10017330f729Sjoerg return;
10027330f729Sjoerg
10037330f729Sjoerg StringRef DiagTypeStr;
10047330f729Sjoerg if (!S.checkStringLiteralArgumentAttr(AL, 2, DiagTypeStr))
10057330f729Sjoerg return;
10067330f729Sjoerg
10077330f729Sjoerg DiagnoseIfAttr::DiagnosticType DiagType;
10087330f729Sjoerg if (!DiagnoseIfAttr::ConvertStrToDiagnosticType(DiagTypeStr, DiagType)) {
10097330f729Sjoerg S.Diag(AL.getArgAsExpr(2)->getBeginLoc(),
10107330f729Sjoerg diag::err_diagnose_if_invalid_diagnostic_type);
10117330f729Sjoerg return;
10127330f729Sjoerg }
10137330f729Sjoerg
10147330f729Sjoerg bool ArgDependent = false;
10157330f729Sjoerg if (const auto *FD = dyn_cast<FunctionDecl>(D))
10167330f729Sjoerg ArgDependent = ArgumentDependenceChecker(FD).referencesArgs(Cond);
10177330f729Sjoerg D->addAttr(::new (S.Context) DiagnoseIfAttr(
10187330f729Sjoerg S.Context, AL, Cond, Msg, DiagType, ArgDependent, cast<NamedDecl>(D)));
10197330f729Sjoerg }
10207330f729Sjoerg
handleNoBuiltinAttr(Sema & S,Decl * D,const ParsedAttr & AL)1021*e038c9c4Sjoerg static void handleNoBuiltinAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
1022*e038c9c4Sjoerg static constexpr const StringRef kWildcard = "*";
1023*e038c9c4Sjoerg
1024*e038c9c4Sjoerg llvm::SmallVector<StringRef, 16> Names;
1025*e038c9c4Sjoerg bool HasWildcard = false;
1026*e038c9c4Sjoerg
1027*e038c9c4Sjoerg const auto AddBuiltinName = [&Names, &HasWildcard](StringRef Name) {
1028*e038c9c4Sjoerg if (Name == kWildcard)
1029*e038c9c4Sjoerg HasWildcard = true;
1030*e038c9c4Sjoerg Names.push_back(Name);
1031*e038c9c4Sjoerg };
1032*e038c9c4Sjoerg
1033*e038c9c4Sjoerg // Add previously defined attributes.
1034*e038c9c4Sjoerg if (const auto *NBA = D->getAttr<NoBuiltinAttr>())
1035*e038c9c4Sjoerg for (StringRef BuiltinName : NBA->builtinNames())
1036*e038c9c4Sjoerg AddBuiltinName(BuiltinName);
1037*e038c9c4Sjoerg
1038*e038c9c4Sjoerg // Add current attributes.
1039*e038c9c4Sjoerg if (AL.getNumArgs() == 0)
1040*e038c9c4Sjoerg AddBuiltinName(kWildcard);
1041*e038c9c4Sjoerg else
1042*e038c9c4Sjoerg for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
1043*e038c9c4Sjoerg StringRef BuiltinName;
1044*e038c9c4Sjoerg SourceLocation LiteralLoc;
1045*e038c9c4Sjoerg if (!S.checkStringLiteralArgumentAttr(AL, I, BuiltinName, &LiteralLoc))
1046*e038c9c4Sjoerg return;
1047*e038c9c4Sjoerg
1048*e038c9c4Sjoerg if (Builtin::Context::isBuiltinFunc(BuiltinName))
1049*e038c9c4Sjoerg AddBuiltinName(BuiltinName);
1050*e038c9c4Sjoerg else
1051*e038c9c4Sjoerg S.Diag(LiteralLoc, diag::warn_attribute_no_builtin_invalid_builtin_name)
1052*e038c9c4Sjoerg << BuiltinName << AL;
1053*e038c9c4Sjoerg }
1054*e038c9c4Sjoerg
1055*e038c9c4Sjoerg // Repeating the same attribute is fine.
1056*e038c9c4Sjoerg llvm::sort(Names);
1057*e038c9c4Sjoerg Names.erase(std::unique(Names.begin(), Names.end()), Names.end());
1058*e038c9c4Sjoerg
1059*e038c9c4Sjoerg // Empty no_builtin must be on its own.
1060*e038c9c4Sjoerg if (HasWildcard && Names.size() > 1)
1061*e038c9c4Sjoerg S.Diag(D->getLocation(),
1062*e038c9c4Sjoerg diag::err_attribute_no_builtin_wildcard_or_builtin_name)
1063*e038c9c4Sjoerg << AL;
1064*e038c9c4Sjoerg
1065*e038c9c4Sjoerg if (D->hasAttr<NoBuiltinAttr>())
1066*e038c9c4Sjoerg D->dropAttr<NoBuiltinAttr>();
1067*e038c9c4Sjoerg D->addAttr(::new (S.Context)
1068*e038c9c4Sjoerg NoBuiltinAttr(S.Context, AL, Names.data(), Names.size()));
1069*e038c9c4Sjoerg }
1070*e038c9c4Sjoerg
handlePassObjectSizeAttr(Sema & S,Decl * D,const ParsedAttr & AL)10717330f729Sjoerg static void handlePassObjectSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
10727330f729Sjoerg if (D->hasAttr<PassObjectSizeAttr>()) {
10737330f729Sjoerg S.Diag(D->getBeginLoc(), diag::err_attribute_only_once_per_parameter) << AL;
10747330f729Sjoerg return;
10757330f729Sjoerg }
10767330f729Sjoerg
10777330f729Sjoerg Expr *E = AL.getArgAsExpr(0);
10787330f729Sjoerg uint32_t Type;
10797330f729Sjoerg if (!checkUInt32Argument(S, AL, E, Type, /*Idx=*/1))
10807330f729Sjoerg return;
10817330f729Sjoerg
10827330f729Sjoerg // pass_object_size's argument is passed in as the second argument of
10837330f729Sjoerg // __builtin_object_size. So, it has the same constraints as that second
10847330f729Sjoerg // argument; namely, it must be in the range [0, 3].
10857330f729Sjoerg if (Type > 3) {
10867330f729Sjoerg S.Diag(E->getBeginLoc(), diag::err_attribute_argument_out_of_range)
10877330f729Sjoerg << AL << 0 << 3 << E->getSourceRange();
10887330f729Sjoerg return;
10897330f729Sjoerg }
10907330f729Sjoerg
10917330f729Sjoerg // pass_object_size is only supported on constant pointer parameters; as a
10927330f729Sjoerg // kindness to users, we allow the parameter to be non-const for declarations.
10937330f729Sjoerg // At this point, we have no clue if `D` belongs to a function declaration or
10947330f729Sjoerg // definition, so we defer the constness check until later.
10957330f729Sjoerg if (!cast<ParmVarDecl>(D)->getType()->isPointerType()) {
10967330f729Sjoerg S.Diag(D->getBeginLoc(), diag::err_attribute_pointers_only) << AL << 1;
10977330f729Sjoerg return;
10987330f729Sjoerg }
10997330f729Sjoerg
11007330f729Sjoerg D->addAttr(::new (S.Context) PassObjectSizeAttr(S.Context, AL, (int)Type));
11017330f729Sjoerg }
11027330f729Sjoerg
handleConsumableAttr(Sema & S,Decl * D,const ParsedAttr & AL)11037330f729Sjoerg static void handleConsumableAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
11047330f729Sjoerg ConsumableAttr::ConsumedState DefaultState;
11057330f729Sjoerg
11067330f729Sjoerg if (AL.isArgIdent(0)) {
11077330f729Sjoerg IdentifierLoc *IL = AL.getArgAsIdent(0);
11087330f729Sjoerg if (!ConsumableAttr::ConvertStrToConsumedState(IL->Ident->getName(),
11097330f729Sjoerg DefaultState)) {
11107330f729Sjoerg S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << AL
11117330f729Sjoerg << IL->Ident;
11127330f729Sjoerg return;
11137330f729Sjoerg }
11147330f729Sjoerg } else {
11157330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
11167330f729Sjoerg << AL << AANT_ArgumentIdentifier;
11177330f729Sjoerg return;
11187330f729Sjoerg }
11197330f729Sjoerg
11207330f729Sjoerg D->addAttr(::new (S.Context) ConsumableAttr(S.Context, AL, DefaultState));
11217330f729Sjoerg }
11227330f729Sjoerg
checkForConsumableClass(Sema & S,const CXXMethodDecl * MD,const ParsedAttr & AL)11237330f729Sjoerg static bool checkForConsumableClass(Sema &S, const CXXMethodDecl *MD,
11247330f729Sjoerg const ParsedAttr &AL) {
11257330f729Sjoerg QualType ThisType = MD->getThisType()->getPointeeType();
11267330f729Sjoerg
11277330f729Sjoerg if (const CXXRecordDecl *RD = ThisType->getAsCXXRecordDecl()) {
11287330f729Sjoerg if (!RD->hasAttr<ConsumableAttr>()) {
1129*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::warn_attr_on_unconsumable_class) << RD;
11307330f729Sjoerg
11317330f729Sjoerg return false;
11327330f729Sjoerg }
11337330f729Sjoerg }
11347330f729Sjoerg
11357330f729Sjoerg return true;
11367330f729Sjoerg }
11377330f729Sjoerg
handleCallableWhenAttr(Sema & S,Decl * D,const ParsedAttr & AL)11387330f729Sjoerg static void handleCallableWhenAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
1139*e038c9c4Sjoerg if (!AL.checkAtLeastNumArgs(S, 1))
11407330f729Sjoerg return;
11417330f729Sjoerg
11427330f729Sjoerg if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), AL))
11437330f729Sjoerg return;
11447330f729Sjoerg
11457330f729Sjoerg SmallVector<CallableWhenAttr::ConsumedState, 3> States;
11467330f729Sjoerg for (unsigned ArgIndex = 0; ArgIndex < AL.getNumArgs(); ++ArgIndex) {
11477330f729Sjoerg CallableWhenAttr::ConsumedState CallableState;
11487330f729Sjoerg
11497330f729Sjoerg StringRef StateString;
11507330f729Sjoerg SourceLocation Loc;
11517330f729Sjoerg if (AL.isArgIdent(ArgIndex)) {
11527330f729Sjoerg IdentifierLoc *Ident = AL.getArgAsIdent(ArgIndex);
11537330f729Sjoerg StateString = Ident->Ident->getName();
11547330f729Sjoerg Loc = Ident->Loc;
11557330f729Sjoerg } else {
11567330f729Sjoerg if (!S.checkStringLiteralArgumentAttr(AL, ArgIndex, StateString, &Loc))
11577330f729Sjoerg return;
11587330f729Sjoerg }
11597330f729Sjoerg
11607330f729Sjoerg if (!CallableWhenAttr::ConvertStrToConsumedState(StateString,
11617330f729Sjoerg CallableState)) {
11627330f729Sjoerg S.Diag(Loc, diag::warn_attribute_type_not_supported) << AL << StateString;
11637330f729Sjoerg return;
11647330f729Sjoerg }
11657330f729Sjoerg
11667330f729Sjoerg States.push_back(CallableState);
11677330f729Sjoerg }
11687330f729Sjoerg
11697330f729Sjoerg D->addAttr(::new (S.Context)
11707330f729Sjoerg CallableWhenAttr(S.Context, AL, States.data(), States.size()));
11717330f729Sjoerg }
11727330f729Sjoerg
handleParamTypestateAttr(Sema & S,Decl * D,const ParsedAttr & AL)11737330f729Sjoerg static void handleParamTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
11747330f729Sjoerg ParamTypestateAttr::ConsumedState ParamState;
11757330f729Sjoerg
11767330f729Sjoerg if (AL.isArgIdent(0)) {
11777330f729Sjoerg IdentifierLoc *Ident = AL.getArgAsIdent(0);
11787330f729Sjoerg StringRef StateString = Ident->Ident->getName();
11797330f729Sjoerg
11807330f729Sjoerg if (!ParamTypestateAttr::ConvertStrToConsumedState(StateString,
11817330f729Sjoerg ParamState)) {
11827330f729Sjoerg S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported)
11837330f729Sjoerg << AL << StateString;
11847330f729Sjoerg return;
11857330f729Sjoerg }
11867330f729Sjoerg } else {
11877330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
11887330f729Sjoerg << AL << AANT_ArgumentIdentifier;
11897330f729Sjoerg return;
11907330f729Sjoerg }
11917330f729Sjoerg
11927330f729Sjoerg // FIXME: This check is currently being done in the analysis. It can be
11937330f729Sjoerg // enabled here only after the parser propagates attributes at
11947330f729Sjoerg // template specialization definition, not declaration.
11957330f729Sjoerg //QualType ReturnType = cast<ParmVarDecl>(D)->getType();
11967330f729Sjoerg //const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl();
11977330f729Sjoerg //
11987330f729Sjoerg //if (!RD || !RD->hasAttr<ConsumableAttr>()) {
11997330f729Sjoerg // S.Diag(AL.getLoc(), diag::warn_return_state_for_unconsumable_type) <<
12007330f729Sjoerg // ReturnType.getAsString();
12017330f729Sjoerg // return;
12027330f729Sjoerg //}
12037330f729Sjoerg
12047330f729Sjoerg D->addAttr(::new (S.Context) ParamTypestateAttr(S.Context, AL, ParamState));
12057330f729Sjoerg }
12067330f729Sjoerg
handleReturnTypestateAttr(Sema & S,Decl * D,const ParsedAttr & AL)12077330f729Sjoerg static void handleReturnTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
12087330f729Sjoerg ReturnTypestateAttr::ConsumedState ReturnState;
12097330f729Sjoerg
12107330f729Sjoerg if (AL.isArgIdent(0)) {
12117330f729Sjoerg IdentifierLoc *IL = AL.getArgAsIdent(0);
12127330f729Sjoerg if (!ReturnTypestateAttr::ConvertStrToConsumedState(IL->Ident->getName(),
12137330f729Sjoerg ReturnState)) {
12147330f729Sjoerg S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << AL
12157330f729Sjoerg << IL->Ident;
12167330f729Sjoerg return;
12177330f729Sjoerg }
12187330f729Sjoerg } else {
12197330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
12207330f729Sjoerg << AL << AANT_ArgumentIdentifier;
12217330f729Sjoerg return;
12227330f729Sjoerg }
12237330f729Sjoerg
12247330f729Sjoerg // FIXME: This check is currently being done in the analysis. It can be
12257330f729Sjoerg // enabled here only after the parser propagates attributes at
12267330f729Sjoerg // template specialization definition, not declaration.
12277330f729Sjoerg //QualType ReturnType;
12287330f729Sjoerg //
12297330f729Sjoerg //if (const ParmVarDecl *Param = dyn_cast<ParmVarDecl>(D)) {
12307330f729Sjoerg // ReturnType = Param->getType();
12317330f729Sjoerg //
12327330f729Sjoerg //} else if (const CXXConstructorDecl *Constructor =
12337330f729Sjoerg // dyn_cast<CXXConstructorDecl>(D)) {
12347330f729Sjoerg // ReturnType = Constructor->getThisType()->getPointeeType();
12357330f729Sjoerg //
12367330f729Sjoerg //} else {
12377330f729Sjoerg //
12387330f729Sjoerg // ReturnType = cast<FunctionDecl>(D)->getCallResultType();
12397330f729Sjoerg //}
12407330f729Sjoerg //
12417330f729Sjoerg //const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl();
12427330f729Sjoerg //
12437330f729Sjoerg //if (!RD || !RD->hasAttr<ConsumableAttr>()) {
12447330f729Sjoerg // S.Diag(Attr.getLoc(), diag::warn_return_state_for_unconsumable_type) <<
12457330f729Sjoerg // ReturnType.getAsString();
12467330f729Sjoerg // return;
12477330f729Sjoerg //}
12487330f729Sjoerg
12497330f729Sjoerg D->addAttr(::new (S.Context) ReturnTypestateAttr(S.Context, AL, ReturnState));
12507330f729Sjoerg }
12517330f729Sjoerg
handleSetTypestateAttr(Sema & S,Decl * D,const ParsedAttr & AL)12527330f729Sjoerg static void handleSetTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
12537330f729Sjoerg if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), AL))
12547330f729Sjoerg return;
12557330f729Sjoerg
12567330f729Sjoerg SetTypestateAttr::ConsumedState NewState;
12577330f729Sjoerg if (AL.isArgIdent(0)) {
12587330f729Sjoerg IdentifierLoc *Ident = AL.getArgAsIdent(0);
12597330f729Sjoerg StringRef Param = Ident->Ident->getName();
12607330f729Sjoerg if (!SetTypestateAttr::ConvertStrToConsumedState(Param, NewState)) {
12617330f729Sjoerg S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) << AL
12627330f729Sjoerg << Param;
12637330f729Sjoerg return;
12647330f729Sjoerg }
12657330f729Sjoerg } else {
12667330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
12677330f729Sjoerg << AL << AANT_ArgumentIdentifier;
12687330f729Sjoerg return;
12697330f729Sjoerg }
12707330f729Sjoerg
12717330f729Sjoerg D->addAttr(::new (S.Context) SetTypestateAttr(S.Context, AL, NewState));
12727330f729Sjoerg }
12737330f729Sjoerg
handleTestTypestateAttr(Sema & S,Decl * D,const ParsedAttr & AL)12747330f729Sjoerg static void handleTestTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
12757330f729Sjoerg if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), AL))
12767330f729Sjoerg return;
12777330f729Sjoerg
12787330f729Sjoerg TestTypestateAttr::ConsumedState TestState;
12797330f729Sjoerg if (AL.isArgIdent(0)) {
12807330f729Sjoerg IdentifierLoc *Ident = AL.getArgAsIdent(0);
12817330f729Sjoerg StringRef Param = Ident->Ident->getName();
12827330f729Sjoerg if (!TestTypestateAttr::ConvertStrToConsumedState(Param, TestState)) {
12837330f729Sjoerg S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) << AL
12847330f729Sjoerg << Param;
12857330f729Sjoerg return;
12867330f729Sjoerg }
12877330f729Sjoerg } else {
12887330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
12897330f729Sjoerg << AL << AANT_ArgumentIdentifier;
12907330f729Sjoerg return;
12917330f729Sjoerg }
12927330f729Sjoerg
12937330f729Sjoerg D->addAttr(::new (S.Context) TestTypestateAttr(S.Context, AL, TestState));
12947330f729Sjoerg }
12957330f729Sjoerg
handleExtVectorTypeAttr(Sema & S,Decl * D,const ParsedAttr & AL)12967330f729Sjoerg static void handleExtVectorTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
12977330f729Sjoerg // Remember this typedef decl, we will need it later for diagnostics.
12987330f729Sjoerg S.ExtVectorDecls.push_back(cast<TypedefNameDecl>(D));
12997330f729Sjoerg }
13007330f729Sjoerg
handlePackedAttr(Sema & S,Decl * D,const ParsedAttr & AL)13017330f729Sjoerg static void handlePackedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
13027330f729Sjoerg if (auto *TD = dyn_cast<TagDecl>(D))
13037330f729Sjoerg TD->addAttr(::new (S.Context) PackedAttr(S.Context, AL));
13047330f729Sjoerg else if (auto *FD = dyn_cast<FieldDecl>(D)) {
13057330f729Sjoerg bool BitfieldByteAligned = (!FD->getType()->isDependentType() &&
13067330f729Sjoerg !FD->getType()->isIncompleteType() &&
13077330f729Sjoerg FD->isBitField() &&
13087330f729Sjoerg S.Context.getTypeAlign(FD->getType()) <= 8);
13097330f729Sjoerg
13107330f729Sjoerg if (S.getASTContext().getTargetInfo().getTriple().isPS4()) {
13117330f729Sjoerg if (BitfieldByteAligned)
13127330f729Sjoerg // The PS4 target needs to maintain ABI backwards compatibility.
13137330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_ignored_for_field_of_type)
13147330f729Sjoerg << AL << FD->getType();
13157330f729Sjoerg else
13167330f729Sjoerg FD->addAttr(::new (S.Context) PackedAttr(S.Context, AL));
13177330f729Sjoerg } else {
13187330f729Sjoerg // Report warning about changed offset in the newer compiler versions.
13197330f729Sjoerg if (BitfieldByteAligned)
13207330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_packed_for_bitfield);
13217330f729Sjoerg
13227330f729Sjoerg FD->addAttr(::new (S.Context) PackedAttr(S.Context, AL));
13237330f729Sjoerg }
13247330f729Sjoerg
13257330f729Sjoerg } else
13267330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL;
13277330f729Sjoerg }
13287330f729Sjoerg
handlePreferredName(Sema & S,Decl * D,const ParsedAttr & AL)1329*e038c9c4Sjoerg static void handlePreferredName(Sema &S, Decl *D, const ParsedAttr &AL) {
1330*e038c9c4Sjoerg auto *RD = cast<CXXRecordDecl>(D);
1331*e038c9c4Sjoerg ClassTemplateDecl *CTD = RD->getDescribedClassTemplate();
1332*e038c9c4Sjoerg assert(CTD && "attribute does not appertain to this declaration");
1333*e038c9c4Sjoerg
1334*e038c9c4Sjoerg ParsedType PT = AL.getTypeArg();
1335*e038c9c4Sjoerg TypeSourceInfo *TSI = nullptr;
1336*e038c9c4Sjoerg QualType T = S.GetTypeFromParser(PT, &TSI);
1337*e038c9c4Sjoerg if (!TSI)
1338*e038c9c4Sjoerg TSI = S.Context.getTrivialTypeSourceInfo(T, AL.getLoc());
1339*e038c9c4Sjoerg
1340*e038c9c4Sjoerg if (!T.hasQualifiers() && T->isTypedefNameType()) {
1341*e038c9c4Sjoerg // Find the template name, if this type names a template specialization.
1342*e038c9c4Sjoerg const TemplateDecl *Template = nullptr;
1343*e038c9c4Sjoerg if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(
1344*e038c9c4Sjoerg T->getAsCXXRecordDecl())) {
1345*e038c9c4Sjoerg Template = CTSD->getSpecializedTemplate();
1346*e038c9c4Sjoerg } else if (const auto *TST = T->getAs<TemplateSpecializationType>()) {
1347*e038c9c4Sjoerg while (TST && TST->isTypeAlias())
1348*e038c9c4Sjoerg TST = TST->getAliasedType()->getAs<TemplateSpecializationType>();
1349*e038c9c4Sjoerg if (TST)
1350*e038c9c4Sjoerg Template = TST->getTemplateName().getAsTemplateDecl();
1351*e038c9c4Sjoerg }
1352*e038c9c4Sjoerg
1353*e038c9c4Sjoerg if (Template && declaresSameEntity(Template, CTD)) {
1354*e038c9c4Sjoerg D->addAttr(::new (S.Context) PreferredNameAttr(S.Context, AL, TSI));
1355*e038c9c4Sjoerg return;
1356*e038c9c4Sjoerg }
1357*e038c9c4Sjoerg }
1358*e038c9c4Sjoerg
1359*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_preferred_name_arg_invalid)
1360*e038c9c4Sjoerg << T << CTD;
1361*e038c9c4Sjoerg if (const auto *TT = T->getAs<TypedefType>())
1362*e038c9c4Sjoerg S.Diag(TT->getDecl()->getLocation(), diag::note_entity_declared_at)
1363*e038c9c4Sjoerg << TT->getDecl();
1364*e038c9c4Sjoerg }
1365*e038c9c4Sjoerg
checkIBOutletCommon(Sema & S,Decl * D,const ParsedAttr & AL)13667330f729Sjoerg static bool checkIBOutletCommon(Sema &S, Decl *D, const ParsedAttr &AL) {
13677330f729Sjoerg // The IBOutlet/IBOutletCollection attributes only apply to instance
13687330f729Sjoerg // variables or properties of Objective-C classes. The outlet must also
13697330f729Sjoerg // have an object reference type.
13707330f729Sjoerg if (const auto *VD = dyn_cast<ObjCIvarDecl>(D)) {
13717330f729Sjoerg if (!VD->getType()->getAs<ObjCObjectPointerType>()) {
13727330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_iboutlet_object_type)
13737330f729Sjoerg << AL << VD->getType() << 0;
13747330f729Sjoerg return false;
13757330f729Sjoerg }
13767330f729Sjoerg }
13777330f729Sjoerg else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) {
13787330f729Sjoerg if (!PD->getType()->getAs<ObjCObjectPointerType>()) {
13797330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_iboutlet_object_type)
13807330f729Sjoerg << AL << PD->getType() << 1;
13817330f729Sjoerg return false;
13827330f729Sjoerg }
13837330f729Sjoerg }
13847330f729Sjoerg else {
13857330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_iboutlet) << AL;
13867330f729Sjoerg return false;
13877330f729Sjoerg }
13887330f729Sjoerg
13897330f729Sjoerg return true;
13907330f729Sjoerg }
13917330f729Sjoerg
handleIBOutlet(Sema & S,Decl * D,const ParsedAttr & AL)13927330f729Sjoerg static void handleIBOutlet(Sema &S, Decl *D, const ParsedAttr &AL) {
13937330f729Sjoerg if (!checkIBOutletCommon(S, D, AL))
13947330f729Sjoerg return;
13957330f729Sjoerg
13967330f729Sjoerg D->addAttr(::new (S.Context) IBOutletAttr(S.Context, AL));
13977330f729Sjoerg }
13987330f729Sjoerg
handleIBOutletCollection(Sema & S,Decl * D,const ParsedAttr & AL)13997330f729Sjoerg static void handleIBOutletCollection(Sema &S, Decl *D, const ParsedAttr &AL) {
14007330f729Sjoerg
14017330f729Sjoerg // The iboutletcollection attribute can have zero or one arguments.
14027330f729Sjoerg if (AL.getNumArgs() > 1) {
14037330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
14047330f729Sjoerg return;
14057330f729Sjoerg }
14067330f729Sjoerg
14077330f729Sjoerg if (!checkIBOutletCommon(S, D, AL))
14087330f729Sjoerg return;
14097330f729Sjoerg
14107330f729Sjoerg ParsedType PT;
14117330f729Sjoerg
14127330f729Sjoerg if (AL.hasParsedType())
14137330f729Sjoerg PT = AL.getTypeArg();
14147330f729Sjoerg else {
14157330f729Sjoerg PT = S.getTypeName(S.Context.Idents.get("NSObject"), AL.getLoc(),
14167330f729Sjoerg S.getScopeForContext(D->getDeclContext()->getParent()));
14177330f729Sjoerg if (!PT) {
14187330f729Sjoerg S.Diag(AL.getLoc(), diag::err_iboutletcollection_type) << "NSObject";
14197330f729Sjoerg return;
14207330f729Sjoerg }
14217330f729Sjoerg }
14227330f729Sjoerg
14237330f729Sjoerg TypeSourceInfo *QTLoc = nullptr;
14247330f729Sjoerg QualType QT = S.GetTypeFromParser(PT, &QTLoc);
14257330f729Sjoerg if (!QTLoc)
14267330f729Sjoerg QTLoc = S.Context.getTrivialTypeSourceInfo(QT, AL.getLoc());
14277330f729Sjoerg
14287330f729Sjoerg // Diagnose use of non-object type in iboutletcollection attribute.
14297330f729Sjoerg // FIXME. Gnu attribute extension ignores use of builtin types in
14307330f729Sjoerg // attributes. So, __attribute__((iboutletcollection(char))) will be
14317330f729Sjoerg // treated as __attribute__((iboutletcollection())).
14327330f729Sjoerg if (!QT->isObjCIdType() && !QT->isObjCObjectType()) {
14337330f729Sjoerg S.Diag(AL.getLoc(),
14347330f729Sjoerg QT->isBuiltinType() ? diag::err_iboutletcollection_builtintype
14357330f729Sjoerg : diag::err_iboutletcollection_type) << QT;
14367330f729Sjoerg return;
14377330f729Sjoerg }
14387330f729Sjoerg
14397330f729Sjoerg D->addAttr(::new (S.Context) IBOutletCollectionAttr(S.Context, AL, QTLoc));
14407330f729Sjoerg }
14417330f729Sjoerg
isValidPointerAttrType(QualType T,bool RefOkay)14427330f729Sjoerg bool Sema::isValidPointerAttrType(QualType T, bool RefOkay) {
14437330f729Sjoerg if (RefOkay) {
14447330f729Sjoerg if (T->isReferenceType())
14457330f729Sjoerg return true;
14467330f729Sjoerg } else {
14477330f729Sjoerg T = T.getNonReferenceType();
14487330f729Sjoerg }
14497330f729Sjoerg
14507330f729Sjoerg // The nonnull attribute, and other similar attributes, can be applied to a
14517330f729Sjoerg // transparent union that contains a pointer type.
14527330f729Sjoerg if (const RecordType *UT = T->getAsUnionType()) {
14537330f729Sjoerg if (UT && UT->getDecl()->hasAttr<TransparentUnionAttr>()) {
14547330f729Sjoerg RecordDecl *UD = UT->getDecl();
14557330f729Sjoerg for (const auto *I : UD->fields()) {
14567330f729Sjoerg QualType QT = I->getType();
14577330f729Sjoerg if (QT->isAnyPointerType() || QT->isBlockPointerType())
14587330f729Sjoerg return true;
14597330f729Sjoerg }
14607330f729Sjoerg }
14617330f729Sjoerg }
14627330f729Sjoerg
14637330f729Sjoerg return T->isAnyPointerType() || T->isBlockPointerType();
14647330f729Sjoerg }
14657330f729Sjoerg
attrNonNullArgCheck(Sema & S,QualType T,const ParsedAttr & AL,SourceRange AttrParmRange,SourceRange TypeRange,bool isReturnValue=false)14667330f729Sjoerg static bool attrNonNullArgCheck(Sema &S, QualType T, const ParsedAttr &AL,
14677330f729Sjoerg SourceRange AttrParmRange,
14687330f729Sjoerg SourceRange TypeRange,
14697330f729Sjoerg bool isReturnValue = false) {
14707330f729Sjoerg if (!S.isValidPointerAttrType(T)) {
14717330f729Sjoerg if (isReturnValue)
14727330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only)
14737330f729Sjoerg << AL << AttrParmRange << TypeRange;
14747330f729Sjoerg else
14757330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_pointers_only)
14767330f729Sjoerg << AL << AttrParmRange << TypeRange << 0;
14777330f729Sjoerg return false;
14787330f729Sjoerg }
14797330f729Sjoerg return true;
14807330f729Sjoerg }
14817330f729Sjoerg
handleNonNullAttr(Sema & S,Decl * D,const ParsedAttr & AL)14827330f729Sjoerg static void handleNonNullAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
14837330f729Sjoerg SmallVector<ParamIdx, 8> NonNullArgs;
14847330f729Sjoerg for (unsigned I = 0; I < AL.getNumArgs(); ++I) {
14857330f729Sjoerg Expr *Ex = AL.getArgAsExpr(I);
14867330f729Sjoerg ParamIdx Idx;
14877330f729Sjoerg if (!checkFunctionOrMethodParameterIndex(S, D, AL, I + 1, Ex, Idx))
14887330f729Sjoerg return;
14897330f729Sjoerg
14907330f729Sjoerg // Is the function argument a pointer type?
14917330f729Sjoerg if (Idx.getASTIndex() < getFunctionOrMethodNumParams(D) &&
14927330f729Sjoerg !attrNonNullArgCheck(
14937330f729Sjoerg S, getFunctionOrMethodParamType(D, Idx.getASTIndex()), AL,
14947330f729Sjoerg Ex->getSourceRange(),
14957330f729Sjoerg getFunctionOrMethodParamRange(D, Idx.getASTIndex())))
14967330f729Sjoerg continue;
14977330f729Sjoerg
14987330f729Sjoerg NonNullArgs.push_back(Idx);
14997330f729Sjoerg }
15007330f729Sjoerg
15017330f729Sjoerg // If no arguments were specified to __attribute__((nonnull)) then all pointer
15027330f729Sjoerg // arguments have a nonnull attribute; warn if there aren't any. Skip this
15037330f729Sjoerg // check if the attribute came from a macro expansion or a template
15047330f729Sjoerg // instantiation.
15057330f729Sjoerg if (NonNullArgs.empty() && AL.getLoc().isFileID() &&
15067330f729Sjoerg !S.inTemplateInstantiation()) {
15077330f729Sjoerg bool AnyPointers = isFunctionOrMethodVariadic(D);
15087330f729Sjoerg for (unsigned I = 0, E = getFunctionOrMethodNumParams(D);
15097330f729Sjoerg I != E && !AnyPointers; ++I) {
15107330f729Sjoerg QualType T = getFunctionOrMethodParamType(D, I);
15117330f729Sjoerg if (T->isDependentType() || S.isValidPointerAttrType(T))
15127330f729Sjoerg AnyPointers = true;
15137330f729Sjoerg }
15147330f729Sjoerg
15157330f729Sjoerg if (!AnyPointers)
15167330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_nonnull_no_pointers);
15177330f729Sjoerg }
15187330f729Sjoerg
15197330f729Sjoerg ParamIdx *Start = NonNullArgs.data();
15207330f729Sjoerg unsigned Size = NonNullArgs.size();
15217330f729Sjoerg llvm::array_pod_sort(Start, Start + Size);
15227330f729Sjoerg D->addAttr(::new (S.Context) NonNullAttr(S.Context, AL, Start, Size));
15237330f729Sjoerg }
15247330f729Sjoerg
handleNonNullAttrParameter(Sema & S,ParmVarDecl * D,const ParsedAttr & AL)15257330f729Sjoerg static void handleNonNullAttrParameter(Sema &S, ParmVarDecl *D,
15267330f729Sjoerg const ParsedAttr &AL) {
15277330f729Sjoerg if (AL.getNumArgs() > 0) {
15287330f729Sjoerg if (D->getFunctionType()) {
15297330f729Sjoerg handleNonNullAttr(S, D, AL);
15307330f729Sjoerg } else {
15317330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_nonnull_parm_no_args)
15327330f729Sjoerg << D->getSourceRange();
15337330f729Sjoerg }
15347330f729Sjoerg return;
15357330f729Sjoerg }
15367330f729Sjoerg
15377330f729Sjoerg // Is the argument a pointer type?
15387330f729Sjoerg if (!attrNonNullArgCheck(S, D->getType(), AL, SourceRange(),
15397330f729Sjoerg D->getSourceRange()))
15407330f729Sjoerg return;
15417330f729Sjoerg
15427330f729Sjoerg D->addAttr(::new (S.Context) NonNullAttr(S.Context, AL, nullptr, 0));
15437330f729Sjoerg }
15447330f729Sjoerg
handleReturnsNonNullAttr(Sema & S,Decl * D,const ParsedAttr & AL)15457330f729Sjoerg static void handleReturnsNonNullAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
15467330f729Sjoerg QualType ResultType = getFunctionOrMethodResultType(D);
15477330f729Sjoerg SourceRange SR = getFunctionOrMethodResultSourceRange(D);
15487330f729Sjoerg if (!attrNonNullArgCheck(S, ResultType, AL, SourceRange(), SR,
15497330f729Sjoerg /* isReturnValue */ true))
15507330f729Sjoerg return;
15517330f729Sjoerg
15527330f729Sjoerg D->addAttr(::new (S.Context) ReturnsNonNullAttr(S.Context, AL));
15537330f729Sjoerg }
15547330f729Sjoerg
handleNoEscapeAttr(Sema & S,Decl * D,const ParsedAttr & AL)15557330f729Sjoerg static void handleNoEscapeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
15567330f729Sjoerg if (D->isInvalidDecl())
15577330f729Sjoerg return;
15587330f729Sjoerg
15597330f729Sjoerg // noescape only applies to pointer types.
15607330f729Sjoerg QualType T = cast<ParmVarDecl>(D)->getType();
15617330f729Sjoerg if (!S.isValidPointerAttrType(T, /* RefOkay */ true)) {
15627330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_pointers_only)
15637330f729Sjoerg << AL << AL.getRange() << 0;
15647330f729Sjoerg return;
15657330f729Sjoerg }
15667330f729Sjoerg
15677330f729Sjoerg D->addAttr(::new (S.Context) NoEscapeAttr(S.Context, AL));
15687330f729Sjoerg }
15697330f729Sjoerg
handleAssumeAlignedAttr(Sema & S,Decl * D,const ParsedAttr & AL)15707330f729Sjoerg static void handleAssumeAlignedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
15717330f729Sjoerg Expr *E = AL.getArgAsExpr(0),
15727330f729Sjoerg *OE = AL.getNumArgs() > 1 ? AL.getArgAsExpr(1) : nullptr;
15737330f729Sjoerg S.AddAssumeAlignedAttr(D, AL, E, OE);
15747330f729Sjoerg }
15757330f729Sjoerg
handleAllocAlignAttr(Sema & S,Decl * D,const ParsedAttr & AL)15767330f729Sjoerg static void handleAllocAlignAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
15777330f729Sjoerg S.AddAllocAlignAttr(D, AL, AL.getArgAsExpr(0));
15787330f729Sjoerg }
15797330f729Sjoerg
AddAssumeAlignedAttr(Decl * D,const AttributeCommonInfo & CI,Expr * E,Expr * OE)15807330f729Sjoerg void Sema::AddAssumeAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
15817330f729Sjoerg Expr *OE) {
15827330f729Sjoerg QualType ResultType = getFunctionOrMethodResultType(D);
15837330f729Sjoerg SourceRange SR = getFunctionOrMethodResultSourceRange(D);
15847330f729Sjoerg
15857330f729Sjoerg AssumeAlignedAttr TmpAttr(Context, CI, E, OE);
15867330f729Sjoerg SourceLocation AttrLoc = TmpAttr.getLocation();
15877330f729Sjoerg
15887330f729Sjoerg if (!isValidPointerAttrType(ResultType, /* RefOkay */ true)) {
15897330f729Sjoerg Diag(AttrLoc, diag::warn_attribute_return_pointers_refs_only)
15907330f729Sjoerg << &TmpAttr << TmpAttr.getRange() << SR;
15917330f729Sjoerg return;
15927330f729Sjoerg }
15937330f729Sjoerg
15947330f729Sjoerg if (!E->isValueDependent()) {
1595*e038c9c4Sjoerg Optional<llvm::APSInt> I = llvm::APSInt(64);
1596*e038c9c4Sjoerg if (!(I = E->getIntegerConstantExpr(Context))) {
15977330f729Sjoerg if (OE)
15987330f729Sjoerg Diag(AttrLoc, diag::err_attribute_argument_n_type)
15997330f729Sjoerg << &TmpAttr << 1 << AANT_ArgumentIntegerConstant
16007330f729Sjoerg << E->getSourceRange();
16017330f729Sjoerg else
16027330f729Sjoerg Diag(AttrLoc, diag::err_attribute_argument_type)
16037330f729Sjoerg << &TmpAttr << AANT_ArgumentIntegerConstant
16047330f729Sjoerg << E->getSourceRange();
16057330f729Sjoerg return;
16067330f729Sjoerg }
16077330f729Sjoerg
1608*e038c9c4Sjoerg if (!I->isPowerOf2()) {
16097330f729Sjoerg Diag(AttrLoc, diag::err_alignment_not_power_of_two)
16107330f729Sjoerg << E->getSourceRange();
16117330f729Sjoerg return;
16127330f729Sjoerg }
1613*e038c9c4Sjoerg
1614*e038c9c4Sjoerg if (*I > Sema::MaximumAlignment)
1615*e038c9c4Sjoerg Diag(CI.getLoc(), diag::warn_assume_aligned_too_great)
1616*e038c9c4Sjoerg << CI.getRange() << Sema::MaximumAlignment;
16177330f729Sjoerg }
16187330f729Sjoerg
1619*e038c9c4Sjoerg if (OE && !OE->isValueDependent() && !OE->isIntegerConstantExpr(Context)) {
16207330f729Sjoerg Diag(AttrLoc, diag::err_attribute_argument_n_type)
16217330f729Sjoerg << &TmpAttr << 2 << AANT_ArgumentIntegerConstant
16227330f729Sjoerg << OE->getSourceRange();
16237330f729Sjoerg return;
16247330f729Sjoerg }
16257330f729Sjoerg
16267330f729Sjoerg D->addAttr(::new (Context) AssumeAlignedAttr(Context, CI, E, OE));
16277330f729Sjoerg }
16287330f729Sjoerg
AddAllocAlignAttr(Decl * D,const AttributeCommonInfo & CI,Expr * ParamExpr)16297330f729Sjoerg void Sema::AddAllocAlignAttr(Decl *D, const AttributeCommonInfo &CI,
16307330f729Sjoerg Expr *ParamExpr) {
16317330f729Sjoerg QualType ResultType = getFunctionOrMethodResultType(D);
16327330f729Sjoerg
16337330f729Sjoerg AllocAlignAttr TmpAttr(Context, CI, ParamIdx());
16347330f729Sjoerg SourceLocation AttrLoc = CI.getLoc();
16357330f729Sjoerg
16367330f729Sjoerg if (!ResultType->isDependentType() &&
16377330f729Sjoerg !isValidPointerAttrType(ResultType, /* RefOkay */ true)) {
16387330f729Sjoerg Diag(AttrLoc, diag::warn_attribute_return_pointers_refs_only)
16397330f729Sjoerg << &TmpAttr << CI.getRange() << getFunctionOrMethodResultSourceRange(D);
16407330f729Sjoerg return;
16417330f729Sjoerg }
16427330f729Sjoerg
16437330f729Sjoerg ParamIdx Idx;
16447330f729Sjoerg const auto *FuncDecl = cast<FunctionDecl>(D);
16457330f729Sjoerg if (!checkFunctionOrMethodParameterIndex(*this, FuncDecl, TmpAttr,
16467330f729Sjoerg /*AttrArgNum=*/1, ParamExpr, Idx))
16477330f729Sjoerg return;
16487330f729Sjoerg
16497330f729Sjoerg QualType Ty = getFunctionOrMethodParamType(D, Idx.getASTIndex());
1650*e038c9c4Sjoerg if (!Ty->isDependentType() && !Ty->isIntegralType(Context) &&
1651*e038c9c4Sjoerg !Ty->isAlignValT()) {
16527330f729Sjoerg Diag(ParamExpr->getBeginLoc(), diag::err_attribute_integers_only)
16537330f729Sjoerg << &TmpAttr
16547330f729Sjoerg << FuncDecl->getParamDecl(Idx.getASTIndex())->getSourceRange();
16557330f729Sjoerg return;
16567330f729Sjoerg }
16577330f729Sjoerg
16587330f729Sjoerg D->addAttr(::new (Context) AllocAlignAttr(Context, CI, Idx));
16597330f729Sjoerg }
16607330f729Sjoerg
1661*e038c9c4Sjoerg /// Check if \p AssumptionStr is a known assumption and warn if not.
checkAssumptionAttr(Sema & S,SourceLocation Loc,StringRef AssumptionStr)1662*e038c9c4Sjoerg static void checkAssumptionAttr(Sema &S, SourceLocation Loc,
1663*e038c9c4Sjoerg StringRef AssumptionStr) {
1664*e038c9c4Sjoerg if (llvm::KnownAssumptionStrings.count(AssumptionStr))
1665*e038c9c4Sjoerg return;
1666*e038c9c4Sjoerg
1667*e038c9c4Sjoerg unsigned BestEditDistance = 3;
1668*e038c9c4Sjoerg StringRef Suggestion;
1669*e038c9c4Sjoerg for (const auto &KnownAssumptionIt : llvm::KnownAssumptionStrings) {
1670*e038c9c4Sjoerg unsigned EditDistance =
1671*e038c9c4Sjoerg AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
1672*e038c9c4Sjoerg if (EditDistance < BestEditDistance) {
1673*e038c9c4Sjoerg Suggestion = KnownAssumptionIt.getKey();
1674*e038c9c4Sjoerg BestEditDistance = EditDistance;
1675*e038c9c4Sjoerg }
1676*e038c9c4Sjoerg }
1677*e038c9c4Sjoerg
1678*e038c9c4Sjoerg if (!Suggestion.empty())
1679*e038c9c4Sjoerg S.Diag(Loc, diag::warn_assume_attribute_string_unknown_suggested)
1680*e038c9c4Sjoerg << AssumptionStr << Suggestion;
1681*e038c9c4Sjoerg else
1682*e038c9c4Sjoerg S.Diag(Loc, diag::warn_assume_attribute_string_unknown) << AssumptionStr;
1683*e038c9c4Sjoerg }
1684*e038c9c4Sjoerg
handleAssumumptionAttr(Sema & S,Decl * D,const ParsedAttr & AL)1685*e038c9c4Sjoerg static void handleAssumumptionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
1686*e038c9c4Sjoerg // Handle the case where the attribute has a text message.
1687*e038c9c4Sjoerg StringRef Str;
1688*e038c9c4Sjoerg SourceLocation AttrStrLoc;
1689*e038c9c4Sjoerg if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc))
1690*e038c9c4Sjoerg return;
1691*e038c9c4Sjoerg
1692*e038c9c4Sjoerg checkAssumptionAttr(S, AttrStrLoc, Str);
1693*e038c9c4Sjoerg
1694*e038c9c4Sjoerg D->addAttr(::new (S.Context) AssumptionAttr(S.Context, AL, Str));
1695*e038c9c4Sjoerg }
1696*e038c9c4Sjoerg
16977330f729Sjoerg /// Normalize the attribute, __foo__ becomes foo.
16987330f729Sjoerg /// Returns true if normalization was applied.
normalizeName(StringRef & AttrName)16997330f729Sjoerg static bool normalizeName(StringRef &AttrName) {
17007330f729Sjoerg if (AttrName.size() > 4 && AttrName.startswith("__") &&
17017330f729Sjoerg AttrName.endswith("__")) {
17027330f729Sjoerg AttrName = AttrName.drop_front(2).drop_back(2);
17037330f729Sjoerg return true;
17047330f729Sjoerg }
17057330f729Sjoerg return false;
17067330f729Sjoerg }
17077330f729Sjoerg
handleOwnershipAttr(Sema & S,Decl * D,const ParsedAttr & AL)17087330f729Sjoerg static void handleOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
17097330f729Sjoerg // This attribute must be applied to a function declaration. The first
17107330f729Sjoerg // argument to the attribute must be an identifier, the name of the resource,
17117330f729Sjoerg // for example: malloc. The following arguments must be argument indexes, the
17127330f729Sjoerg // arguments must be of integer type for Returns, otherwise of pointer type.
17137330f729Sjoerg // The difference between Holds and Takes is that a pointer may still be used
17147330f729Sjoerg // after being held. free() should be __attribute((ownership_takes)), whereas
17157330f729Sjoerg // a list append function may well be __attribute((ownership_holds)).
17167330f729Sjoerg
17177330f729Sjoerg if (!AL.isArgIdent(0)) {
17187330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
17197330f729Sjoerg << AL << 1 << AANT_ArgumentIdentifier;
17207330f729Sjoerg return;
17217330f729Sjoerg }
17227330f729Sjoerg
17237330f729Sjoerg // Figure out our Kind.
17247330f729Sjoerg OwnershipAttr::OwnershipKind K =
17257330f729Sjoerg OwnershipAttr(S.Context, AL, nullptr, nullptr, 0).getOwnKind();
17267330f729Sjoerg
17277330f729Sjoerg // Check arguments.
17287330f729Sjoerg switch (K) {
17297330f729Sjoerg case OwnershipAttr::Takes:
17307330f729Sjoerg case OwnershipAttr::Holds:
17317330f729Sjoerg if (AL.getNumArgs() < 2) {
17327330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_too_few_arguments) << AL << 2;
17337330f729Sjoerg return;
17347330f729Sjoerg }
17357330f729Sjoerg break;
17367330f729Sjoerg case OwnershipAttr::Returns:
17377330f729Sjoerg if (AL.getNumArgs() > 2) {
17387330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1;
17397330f729Sjoerg return;
17407330f729Sjoerg }
17417330f729Sjoerg break;
17427330f729Sjoerg }
17437330f729Sjoerg
17447330f729Sjoerg IdentifierInfo *Module = AL.getArgAsIdent(0)->Ident;
17457330f729Sjoerg
17467330f729Sjoerg StringRef ModuleName = Module->getName();
17477330f729Sjoerg if (normalizeName(ModuleName)) {
17487330f729Sjoerg Module = &S.PP.getIdentifierTable().get(ModuleName);
17497330f729Sjoerg }
17507330f729Sjoerg
17517330f729Sjoerg SmallVector<ParamIdx, 8> OwnershipArgs;
17527330f729Sjoerg for (unsigned i = 1; i < AL.getNumArgs(); ++i) {
17537330f729Sjoerg Expr *Ex = AL.getArgAsExpr(i);
17547330f729Sjoerg ParamIdx Idx;
17557330f729Sjoerg if (!checkFunctionOrMethodParameterIndex(S, D, AL, i, Ex, Idx))
17567330f729Sjoerg return;
17577330f729Sjoerg
17587330f729Sjoerg // Is the function argument a pointer type?
17597330f729Sjoerg QualType T = getFunctionOrMethodParamType(D, Idx.getASTIndex());
17607330f729Sjoerg int Err = -1; // No error
17617330f729Sjoerg switch (K) {
17627330f729Sjoerg case OwnershipAttr::Takes:
17637330f729Sjoerg case OwnershipAttr::Holds:
17647330f729Sjoerg if (!T->isAnyPointerType() && !T->isBlockPointerType())
17657330f729Sjoerg Err = 0;
17667330f729Sjoerg break;
17677330f729Sjoerg case OwnershipAttr::Returns:
17687330f729Sjoerg if (!T->isIntegerType())
17697330f729Sjoerg Err = 1;
17707330f729Sjoerg break;
17717330f729Sjoerg }
17727330f729Sjoerg if (-1 != Err) {
17737330f729Sjoerg S.Diag(AL.getLoc(), diag::err_ownership_type) << AL << Err
17747330f729Sjoerg << Ex->getSourceRange();
17757330f729Sjoerg return;
17767330f729Sjoerg }
17777330f729Sjoerg
17787330f729Sjoerg // Check we don't have a conflict with another ownership attribute.
17797330f729Sjoerg for (const auto *I : D->specific_attrs<OwnershipAttr>()) {
17807330f729Sjoerg // Cannot have two ownership attributes of different kinds for the same
17817330f729Sjoerg // index.
17827330f729Sjoerg if (I->getOwnKind() != K && I->args_end() !=
17837330f729Sjoerg std::find(I->args_begin(), I->args_end(), Idx)) {
17847330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) << AL << I;
17857330f729Sjoerg return;
17867330f729Sjoerg } else if (K == OwnershipAttr::Returns &&
17877330f729Sjoerg I->getOwnKind() == OwnershipAttr::Returns) {
17887330f729Sjoerg // A returns attribute conflicts with any other returns attribute using
17897330f729Sjoerg // a different index.
17907330f729Sjoerg if (std::find(I->args_begin(), I->args_end(), Idx) == I->args_end()) {
17917330f729Sjoerg S.Diag(I->getLocation(), diag::err_ownership_returns_index_mismatch)
17927330f729Sjoerg << I->args_begin()->getSourceIndex();
17937330f729Sjoerg if (I->args_size())
17947330f729Sjoerg S.Diag(AL.getLoc(), diag::note_ownership_returns_index_mismatch)
17957330f729Sjoerg << Idx.getSourceIndex() << Ex->getSourceRange();
17967330f729Sjoerg return;
17977330f729Sjoerg }
17987330f729Sjoerg }
17997330f729Sjoerg }
18007330f729Sjoerg OwnershipArgs.push_back(Idx);
18017330f729Sjoerg }
18027330f729Sjoerg
18037330f729Sjoerg ParamIdx *Start = OwnershipArgs.data();
18047330f729Sjoerg unsigned Size = OwnershipArgs.size();
18057330f729Sjoerg llvm::array_pod_sort(Start, Start + Size);
18067330f729Sjoerg D->addAttr(::new (S.Context)
18077330f729Sjoerg OwnershipAttr(S.Context, AL, Module, Start, Size));
18087330f729Sjoerg }
18097330f729Sjoerg
handleWeakRefAttr(Sema & S,Decl * D,const ParsedAttr & AL)18107330f729Sjoerg static void handleWeakRefAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
18117330f729Sjoerg // Check the attribute arguments.
18127330f729Sjoerg if (AL.getNumArgs() > 1) {
18137330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
18147330f729Sjoerg return;
18157330f729Sjoerg }
18167330f729Sjoerg
18177330f729Sjoerg // gcc rejects
18187330f729Sjoerg // class c {
18197330f729Sjoerg // static int a __attribute__((weakref ("v2")));
18207330f729Sjoerg // static int b() __attribute__((weakref ("f3")));
18217330f729Sjoerg // };
18227330f729Sjoerg // and ignores the attributes of
18237330f729Sjoerg // void f(void) {
18247330f729Sjoerg // static int a __attribute__((weakref ("v2")));
18257330f729Sjoerg // }
18267330f729Sjoerg // we reject them
18277330f729Sjoerg const DeclContext *Ctx = D->getDeclContext()->getRedeclContext();
18287330f729Sjoerg if (!Ctx->isFileContext()) {
18297330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_weakref_not_global_context)
18307330f729Sjoerg << cast<NamedDecl>(D);
18317330f729Sjoerg return;
18327330f729Sjoerg }
18337330f729Sjoerg
18347330f729Sjoerg // The GCC manual says
18357330f729Sjoerg //
18367330f729Sjoerg // At present, a declaration to which `weakref' is attached can only
18377330f729Sjoerg // be `static'.
18387330f729Sjoerg //
18397330f729Sjoerg // It also says
18407330f729Sjoerg //
18417330f729Sjoerg // Without a TARGET,
18427330f729Sjoerg // given as an argument to `weakref' or to `alias', `weakref' is
18437330f729Sjoerg // equivalent to `weak'.
18447330f729Sjoerg //
18457330f729Sjoerg // gcc 4.4.1 will accept
18467330f729Sjoerg // int a7 __attribute__((weakref));
18477330f729Sjoerg // as
18487330f729Sjoerg // int a7 __attribute__((weak));
18497330f729Sjoerg // This looks like a bug in gcc. We reject that for now. We should revisit
18507330f729Sjoerg // it if this behaviour is actually used.
18517330f729Sjoerg
18527330f729Sjoerg // GCC rejects
18537330f729Sjoerg // static ((alias ("y"), weakref)).
18547330f729Sjoerg // Should we? How to check that weakref is before or after alias?
18557330f729Sjoerg
18567330f729Sjoerg // FIXME: it would be good for us to keep the WeakRefAttr as-written instead
18577330f729Sjoerg // of transforming it into an AliasAttr. The WeakRefAttr never uses the
18587330f729Sjoerg // StringRef parameter it was given anyway.
18597330f729Sjoerg StringRef Str;
18607330f729Sjoerg if (AL.getNumArgs() && S.checkStringLiteralArgumentAttr(AL, 0, Str))
18617330f729Sjoerg // GCC will accept anything as the argument of weakref. Should we
18627330f729Sjoerg // check for an existing decl?
18637330f729Sjoerg D->addAttr(::new (S.Context) AliasAttr(S.Context, AL, Str));
18647330f729Sjoerg
18657330f729Sjoerg D->addAttr(::new (S.Context) WeakRefAttr(S.Context, AL));
18667330f729Sjoerg }
18677330f729Sjoerg
handleIFuncAttr(Sema & S,Decl * D,const ParsedAttr & AL)18687330f729Sjoerg static void handleIFuncAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
18697330f729Sjoerg StringRef Str;
18707330f729Sjoerg if (!S.checkStringLiteralArgumentAttr(AL, 0, Str))
18717330f729Sjoerg return;
18727330f729Sjoerg
18737330f729Sjoerg // Aliases should be on declarations, not definitions.
18747330f729Sjoerg const auto *FD = cast<FunctionDecl>(D);
18757330f729Sjoerg if (FD->isThisDeclarationADefinition()) {
18767330f729Sjoerg S.Diag(AL.getLoc(), diag::err_alias_is_definition) << FD << 1;
18777330f729Sjoerg return;
18787330f729Sjoerg }
18797330f729Sjoerg
18807330f729Sjoerg D->addAttr(::new (S.Context) IFuncAttr(S.Context, AL, Str));
18817330f729Sjoerg }
18827330f729Sjoerg
handleAliasAttr(Sema & S,Decl * D,const ParsedAttr & AL)18837330f729Sjoerg static void handleAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
18847330f729Sjoerg StringRef Str;
18857330f729Sjoerg if (!S.checkStringLiteralArgumentAttr(AL, 0, Str))
18867330f729Sjoerg return;
18877330f729Sjoerg
18887330f729Sjoerg if (S.Context.getTargetInfo().getTriple().isOSDarwin()) {
18897330f729Sjoerg S.Diag(AL.getLoc(), diag::err_alias_not_supported_on_darwin);
18907330f729Sjoerg return;
18917330f729Sjoerg }
18927330f729Sjoerg if (S.Context.getTargetInfo().getTriple().isNVPTX()) {
18937330f729Sjoerg S.Diag(AL.getLoc(), diag::err_alias_not_supported_on_nvptx);
18947330f729Sjoerg }
18957330f729Sjoerg
18967330f729Sjoerg // Aliases should be on declarations, not definitions.
18977330f729Sjoerg if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
18987330f729Sjoerg if (FD->isThisDeclarationADefinition()) {
18997330f729Sjoerg S.Diag(AL.getLoc(), diag::err_alias_is_definition) << FD << 0;
19007330f729Sjoerg return;
19017330f729Sjoerg }
19027330f729Sjoerg } else {
19037330f729Sjoerg const auto *VD = cast<VarDecl>(D);
19047330f729Sjoerg if (VD->isThisDeclarationADefinition() && VD->isExternallyVisible()) {
19057330f729Sjoerg S.Diag(AL.getLoc(), diag::err_alias_is_definition) << VD << 0;
19067330f729Sjoerg return;
19077330f729Sjoerg }
19087330f729Sjoerg }
19097330f729Sjoerg
19107330f729Sjoerg // Mark target used to prevent unneeded-internal-declaration warnings.
19117330f729Sjoerg if (!S.LangOpts.CPlusPlus) {
19127330f729Sjoerg // FIXME: demangle Str for C++, as the attribute refers to the mangled
19137330f729Sjoerg // linkage name, not the pre-mangled identifier.
19147330f729Sjoerg const DeclarationNameInfo target(&S.Context.Idents.get(Str), AL.getLoc());
19157330f729Sjoerg LookupResult LR(S, target, Sema::LookupOrdinaryName);
19167330f729Sjoerg if (S.LookupQualifiedName(LR, S.getCurLexicalContext()))
19177330f729Sjoerg for (NamedDecl *ND : LR)
19187330f729Sjoerg ND->markUsed(S.Context);
19197330f729Sjoerg }
19207330f729Sjoerg
19217330f729Sjoerg D->addAttr(::new (S.Context) AliasAttr(S.Context, AL, Str));
19227330f729Sjoerg }
19237330f729Sjoerg
handleTLSModelAttr(Sema & S,Decl * D,const ParsedAttr & AL)19247330f729Sjoerg static void handleTLSModelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
19257330f729Sjoerg StringRef Model;
19267330f729Sjoerg SourceLocation LiteralLoc;
19277330f729Sjoerg // Check that it is a string.
19287330f729Sjoerg if (!S.checkStringLiteralArgumentAttr(AL, 0, Model, &LiteralLoc))
19297330f729Sjoerg return;
19307330f729Sjoerg
19317330f729Sjoerg // Check that the value.
19327330f729Sjoerg if (Model != "global-dynamic" && Model != "local-dynamic"
19337330f729Sjoerg && Model != "initial-exec" && Model != "local-exec") {
19347330f729Sjoerg S.Diag(LiteralLoc, diag::err_attr_tlsmodel_arg);
19357330f729Sjoerg return;
19367330f729Sjoerg }
19377330f729Sjoerg
1938*e038c9c4Sjoerg if (S.Context.getTargetInfo().getTriple().isOSAIX() &&
1939*e038c9c4Sjoerg Model != "global-dynamic") {
1940*e038c9c4Sjoerg S.Diag(LiteralLoc, diag::err_aix_attr_unsupported_tls_model) << Model;
1941*e038c9c4Sjoerg return;
1942*e038c9c4Sjoerg }
1943*e038c9c4Sjoerg
19447330f729Sjoerg D->addAttr(::new (S.Context) TLSModelAttr(S.Context, AL, Model));
19457330f729Sjoerg }
19467330f729Sjoerg
handleRestrictAttr(Sema & S,Decl * D,const ParsedAttr & AL)19477330f729Sjoerg static void handleRestrictAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
19487330f729Sjoerg QualType ResultType = getFunctionOrMethodResultType(D);
19497330f729Sjoerg if (ResultType->isAnyPointerType() || ResultType->isBlockPointerType()) {
19507330f729Sjoerg D->addAttr(::new (S.Context) RestrictAttr(S.Context, AL));
19517330f729Sjoerg return;
19527330f729Sjoerg }
19537330f729Sjoerg
19547330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only)
19557330f729Sjoerg << AL << getFunctionOrMethodResultSourceRange(D);
19567330f729Sjoerg }
19577330f729Sjoerg
handleCPUSpecificAttr(Sema & S,Decl * D,const ParsedAttr & AL)19587330f729Sjoerg static void handleCPUSpecificAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
19597330f729Sjoerg FunctionDecl *FD = cast<FunctionDecl>(D);
19607330f729Sjoerg
19617330f729Sjoerg if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
19627330f729Sjoerg if (MD->getParent()->isLambda()) {
19637330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_dll_lambda) << AL;
19647330f729Sjoerg return;
19657330f729Sjoerg }
19667330f729Sjoerg }
19677330f729Sjoerg
1968*e038c9c4Sjoerg if (!AL.checkAtLeastNumArgs(S, 1))
19697330f729Sjoerg return;
19707330f729Sjoerg
19717330f729Sjoerg SmallVector<IdentifierInfo *, 8> CPUs;
19727330f729Sjoerg for (unsigned ArgNo = 0; ArgNo < getNumAttributeArgs(AL); ++ArgNo) {
19737330f729Sjoerg if (!AL.isArgIdent(ArgNo)) {
19747330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
19757330f729Sjoerg << AL << AANT_ArgumentIdentifier;
19767330f729Sjoerg return;
19777330f729Sjoerg }
19787330f729Sjoerg
19797330f729Sjoerg IdentifierLoc *CPUArg = AL.getArgAsIdent(ArgNo);
19807330f729Sjoerg StringRef CPUName = CPUArg->Ident->getName().trim();
19817330f729Sjoerg
19827330f729Sjoerg if (!S.Context.getTargetInfo().validateCPUSpecificCPUDispatch(CPUName)) {
19837330f729Sjoerg S.Diag(CPUArg->Loc, diag::err_invalid_cpu_specific_dispatch_value)
19847330f729Sjoerg << CPUName << (AL.getKind() == ParsedAttr::AT_CPUDispatch);
19857330f729Sjoerg return;
19867330f729Sjoerg }
19877330f729Sjoerg
19887330f729Sjoerg const TargetInfo &Target = S.Context.getTargetInfo();
19897330f729Sjoerg if (llvm::any_of(CPUs, [CPUName, &Target](const IdentifierInfo *Cur) {
19907330f729Sjoerg return Target.CPUSpecificManglingCharacter(CPUName) ==
19917330f729Sjoerg Target.CPUSpecificManglingCharacter(Cur->getName());
19927330f729Sjoerg })) {
19937330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_multiversion_duplicate_entries);
19947330f729Sjoerg return;
19957330f729Sjoerg }
19967330f729Sjoerg CPUs.push_back(CPUArg->Ident);
19977330f729Sjoerg }
19987330f729Sjoerg
19997330f729Sjoerg FD->setIsMultiVersion(true);
20007330f729Sjoerg if (AL.getKind() == ParsedAttr::AT_CPUSpecific)
20017330f729Sjoerg D->addAttr(::new (S.Context)
20027330f729Sjoerg CPUSpecificAttr(S.Context, AL, CPUs.data(), CPUs.size()));
20037330f729Sjoerg else
20047330f729Sjoerg D->addAttr(::new (S.Context)
20057330f729Sjoerg CPUDispatchAttr(S.Context, AL, CPUs.data(), CPUs.size()));
20067330f729Sjoerg }
20077330f729Sjoerg
handleCommonAttr(Sema & S,Decl * D,const ParsedAttr & AL)20087330f729Sjoerg static void handleCommonAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
20097330f729Sjoerg if (S.LangOpts.CPlusPlus) {
20107330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang)
20117330f729Sjoerg << AL << AttributeLangSupport::Cpp;
20127330f729Sjoerg return;
20137330f729Sjoerg }
20147330f729Sjoerg
2015*e038c9c4Sjoerg D->addAttr(::new (S.Context) CommonAttr(S.Context, AL));
2016*e038c9c4Sjoerg }
2017*e038c9c4Sjoerg
handleCmseNSEntryAttr(Sema & S,Decl * D,const ParsedAttr & AL)2018*e038c9c4Sjoerg static void handleCmseNSEntryAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
2019*e038c9c4Sjoerg if (S.LangOpts.CPlusPlus && !D->getDeclContext()->isExternCContext()) {
2020*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_not_clinkage) << AL;
2021*e038c9c4Sjoerg return;
2022*e038c9c4Sjoerg }
2023*e038c9c4Sjoerg
2024*e038c9c4Sjoerg const auto *FD = cast<FunctionDecl>(D);
2025*e038c9c4Sjoerg if (!FD->isExternallyVisible()) {
2026*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_cmse_entry_static);
2027*e038c9c4Sjoerg return;
2028*e038c9c4Sjoerg }
2029*e038c9c4Sjoerg
2030*e038c9c4Sjoerg D->addAttr(::new (S.Context) CmseNSEntryAttr(S.Context, AL));
20317330f729Sjoerg }
20327330f729Sjoerg
handleNakedAttr(Sema & S,Decl * D,const ParsedAttr & AL)20337330f729Sjoerg static void handleNakedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
20347330f729Sjoerg if (AL.isDeclspecAttribute()) {
20357330f729Sjoerg const auto &Triple = S.getASTContext().getTargetInfo().getTriple();
20367330f729Sjoerg const auto &Arch = Triple.getArch();
20377330f729Sjoerg if (Arch != llvm::Triple::x86 &&
20387330f729Sjoerg (Arch != llvm::Triple::arm && Arch != llvm::Triple::thumb)) {
20397330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_not_supported_on_arch)
20407330f729Sjoerg << AL << Triple.getArchName();
20417330f729Sjoerg return;
20427330f729Sjoerg }
20437330f729Sjoerg }
20447330f729Sjoerg
20457330f729Sjoerg D->addAttr(::new (S.Context) NakedAttr(S.Context, AL));
20467330f729Sjoerg }
20477330f729Sjoerg
handleNoReturnAttr(Sema & S,Decl * D,const ParsedAttr & Attrs)20487330f729Sjoerg static void handleNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &Attrs) {
20497330f729Sjoerg if (hasDeclarator(D)) return;
20507330f729Sjoerg
20517330f729Sjoerg if (!isa<ObjCMethodDecl>(D)) {
20527330f729Sjoerg S.Diag(Attrs.getLoc(), diag::warn_attribute_wrong_decl_type)
20537330f729Sjoerg << Attrs << ExpectedFunctionOrMethod;
20547330f729Sjoerg return;
20557330f729Sjoerg }
20567330f729Sjoerg
20577330f729Sjoerg D->addAttr(::new (S.Context) NoReturnAttr(S.Context, Attrs));
20587330f729Sjoerg }
20597330f729Sjoerg
handleNoCfCheckAttr(Sema & S,Decl * D,const ParsedAttr & Attrs)20607330f729Sjoerg static void handleNoCfCheckAttr(Sema &S, Decl *D, const ParsedAttr &Attrs) {
20617330f729Sjoerg if (!S.getLangOpts().CFProtectionBranch)
20627330f729Sjoerg S.Diag(Attrs.getLoc(), diag::warn_nocf_check_attribute_ignored);
20637330f729Sjoerg else
20647330f729Sjoerg handleSimpleAttribute<AnyX86NoCfCheckAttr>(S, D, Attrs);
20657330f729Sjoerg }
20667330f729Sjoerg
CheckAttrNoArgs(const ParsedAttr & Attrs)20677330f729Sjoerg bool Sema::CheckAttrNoArgs(const ParsedAttr &Attrs) {
2068*e038c9c4Sjoerg if (!Attrs.checkExactlyNumArgs(*this, 0)) {
20697330f729Sjoerg Attrs.setInvalid();
20707330f729Sjoerg return true;
20717330f729Sjoerg }
20727330f729Sjoerg
20737330f729Sjoerg return false;
20747330f729Sjoerg }
20757330f729Sjoerg
CheckAttrTarget(const ParsedAttr & AL)20767330f729Sjoerg bool Sema::CheckAttrTarget(const ParsedAttr &AL) {
20777330f729Sjoerg // Check whether the attribute is valid on the current target.
20787330f729Sjoerg if (!AL.existsInTarget(Context.getTargetInfo())) {
2079*e038c9c4Sjoerg Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored)
2080*e038c9c4Sjoerg << AL << AL.getRange();
20817330f729Sjoerg AL.setInvalid();
20827330f729Sjoerg return true;
20837330f729Sjoerg }
20847330f729Sjoerg
20857330f729Sjoerg return false;
20867330f729Sjoerg }
20877330f729Sjoerg
handleAnalyzerNoReturnAttr(Sema & S,Decl * D,const ParsedAttr & AL)20887330f729Sjoerg static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
20897330f729Sjoerg
20907330f729Sjoerg // The checking path for 'noreturn' and 'analyzer_noreturn' are different
20917330f729Sjoerg // because 'analyzer_noreturn' does not impact the type.
20927330f729Sjoerg if (!isFunctionOrMethodOrBlock(D)) {
20937330f729Sjoerg ValueDecl *VD = dyn_cast<ValueDecl>(D);
20947330f729Sjoerg if (!VD || (!VD->getType()->isBlockPointerType() &&
20957330f729Sjoerg !VD->getType()->isFunctionPointerType())) {
20967330f729Sjoerg S.Diag(AL.getLoc(), AL.isCXX11Attribute()
20977330f729Sjoerg ? diag::err_attribute_wrong_decl_type
20987330f729Sjoerg : diag::warn_attribute_wrong_decl_type)
20997330f729Sjoerg << AL << ExpectedFunctionMethodOrBlock;
21007330f729Sjoerg return;
21017330f729Sjoerg }
21027330f729Sjoerg }
21037330f729Sjoerg
21047330f729Sjoerg D->addAttr(::new (S.Context) AnalyzerNoReturnAttr(S.Context, AL));
21057330f729Sjoerg }
21067330f729Sjoerg
21077330f729Sjoerg // PS3 PPU-specific.
handleVecReturnAttr(Sema & S,Decl * D,const ParsedAttr & AL)21087330f729Sjoerg static void handleVecReturnAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
21097330f729Sjoerg /*
21107330f729Sjoerg Returning a Vector Class in Registers
21117330f729Sjoerg
21127330f729Sjoerg According to the PPU ABI specifications, a class with a single member of
21137330f729Sjoerg vector type is returned in memory when used as the return value of a
21147330f729Sjoerg function.
21157330f729Sjoerg This results in inefficient code when implementing vector classes. To return
21167330f729Sjoerg the value in a single vector register, add the vecreturn attribute to the
21177330f729Sjoerg class definition. This attribute is also applicable to struct types.
21187330f729Sjoerg
21197330f729Sjoerg Example:
21207330f729Sjoerg
21217330f729Sjoerg struct Vector
21227330f729Sjoerg {
21237330f729Sjoerg __vector float xyzw;
21247330f729Sjoerg } __attribute__((vecreturn));
21257330f729Sjoerg
21267330f729Sjoerg Vector Add(Vector lhs, Vector rhs)
21277330f729Sjoerg {
21287330f729Sjoerg Vector result;
21297330f729Sjoerg result.xyzw = vec_add(lhs.xyzw, rhs.xyzw);
21307330f729Sjoerg return result; // This will be returned in a register
21317330f729Sjoerg }
21327330f729Sjoerg */
21337330f729Sjoerg if (VecReturnAttr *A = D->getAttr<VecReturnAttr>()) {
21347330f729Sjoerg S.Diag(AL.getLoc(), diag::err_repeat_attribute) << A;
21357330f729Sjoerg return;
21367330f729Sjoerg }
21377330f729Sjoerg
21387330f729Sjoerg const auto *R = cast<RecordDecl>(D);
21397330f729Sjoerg int count = 0;
21407330f729Sjoerg
21417330f729Sjoerg if (!isa<CXXRecordDecl>(R)) {
21427330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_vecreturn_only_vector_member);
21437330f729Sjoerg return;
21447330f729Sjoerg }
21457330f729Sjoerg
21467330f729Sjoerg if (!cast<CXXRecordDecl>(R)->isPOD()) {
21477330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_vecreturn_only_pod_record);
21487330f729Sjoerg return;
21497330f729Sjoerg }
21507330f729Sjoerg
21517330f729Sjoerg for (const auto *I : R->fields()) {
21527330f729Sjoerg if ((count == 1) || !I->getType()->isVectorType()) {
21537330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_vecreturn_only_vector_member);
21547330f729Sjoerg return;
21557330f729Sjoerg }
21567330f729Sjoerg count++;
21577330f729Sjoerg }
21587330f729Sjoerg
21597330f729Sjoerg D->addAttr(::new (S.Context) VecReturnAttr(S.Context, AL));
21607330f729Sjoerg }
21617330f729Sjoerg
handleDependencyAttr(Sema & S,Scope * Scope,Decl * D,const ParsedAttr & AL)21627330f729Sjoerg static void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D,
21637330f729Sjoerg const ParsedAttr &AL) {
21647330f729Sjoerg if (isa<ParmVarDecl>(D)) {
21657330f729Sjoerg // [[carries_dependency]] can only be applied to a parameter if it is a
21667330f729Sjoerg // parameter of a function declaration or lambda.
21677330f729Sjoerg if (!(Scope->getFlags() & clang::Scope::FunctionDeclarationScope)) {
21687330f729Sjoerg S.Diag(AL.getLoc(),
21697330f729Sjoerg diag::err_carries_dependency_param_not_function_decl);
21707330f729Sjoerg return;
21717330f729Sjoerg }
21727330f729Sjoerg }
21737330f729Sjoerg
21747330f729Sjoerg D->addAttr(::new (S.Context) CarriesDependencyAttr(S.Context, AL));
21757330f729Sjoerg }
21767330f729Sjoerg
handleUnusedAttr(Sema & S,Decl * D,const ParsedAttr & AL)21777330f729Sjoerg static void handleUnusedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
21787330f729Sjoerg bool IsCXX17Attr = AL.isCXX11Attribute() && !AL.getScopeName();
21797330f729Sjoerg
21807330f729Sjoerg // If this is spelled as the standard C++17 attribute, but not in C++17, warn
21817330f729Sjoerg // about using it as an extension.
21827330f729Sjoerg if (!S.getLangOpts().CPlusPlus17 && IsCXX17Attr)
21837330f729Sjoerg S.Diag(AL.getLoc(), diag::ext_cxx17_attr) << AL;
21847330f729Sjoerg
21857330f729Sjoerg D->addAttr(::new (S.Context) UnusedAttr(S.Context, AL));
21867330f729Sjoerg }
21877330f729Sjoerg
handleConstructorAttr(Sema & S,Decl * D,const ParsedAttr & AL)21887330f729Sjoerg static void handleConstructorAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
21897330f729Sjoerg uint32_t priority = ConstructorAttr::DefaultPriority;
21907330f729Sjoerg if (AL.getNumArgs() &&
21917330f729Sjoerg !checkUInt32Argument(S, AL, AL.getArgAsExpr(0), priority))
21927330f729Sjoerg return;
21937330f729Sjoerg
21947330f729Sjoerg D->addAttr(::new (S.Context) ConstructorAttr(S.Context, AL, priority));
21957330f729Sjoerg }
21967330f729Sjoerg
handleDestructorAttr(Sema & S,Decl * D,const ParsedAttr & AL)21977330f729Sjoerg static void handleDestructorAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
21987330f729Sjoerg uint32_t priority = DestructorAttr::DefaultPriority;
21997330f729Sjoerg if (AL.getNumArgs() &&
22007330f729Sjoerg !checkUInt32Argument(S, AL, AL.getArgAsExpr(0), priority))
22017330f729Sjoerg return;
22027330f729Sjoerg
22037330f729Sjoerg D->addAttr(::new (S.Context) DestructorAttr(S.Context, AL, priority));
22047330f729Sjoerg }
22057330f729Sjoerg
22067330f729Sjoerg template <typename AttrTy>
handleAttrWithMessage(Sema & S,Decl * D,const ParsedAttr & AL)22077330f729Sjoerg static void handleAttrWithMessage(Sema &S, Decl *D, const ParsedAttr &AL) {
22087330f729Sjoerg // Handle the case where the attribute has a text message.
22097330f729Sjoerg StringRef Str;
22107330f729Sjoerg if (AL.getNumArgs() == 1 && !S.checkStringLiteralArgumentAttr(AL, 0, Str))
22117330f729Sjoerg return;
22127330f729Sjoerg
22137330f729Sjoerg D->addAttr(::new (S.Context) AttrTy(S.Context, AL, Str));
22147330f729Sjoerg }
22157330f729Sjoerg
handleObjCSuppresProtocolAttr(Sema & S,Decl * D,const ParsedAttr & AL)22167330f729Sjoerg static void handleObjCSuppresProtocolAttr(Sema &S, Decl *D,
22177330f729Sjoerg const ParsedAttr &AL) {
22187330f729Sjoerg if (!cast<ObjCProtocolDecl>(D)->isThisDeclarationADefinition()) {
22197330f729Sjoerg S.Diag(AL.getLoc(), diag::err_objc_attr_protocol_requires_definition)
22207330f729Sjoerg << AL << AL.getRange();
22217330f729Sjoerg return;
22227330f729Sjoerg }
22237330f729Sjoerg
22247330f729Sjoerg D->addAttr(::new (S.Context) ObjCExplicitProtocolImplAttr(S.Context, AL));
22257330f729Sjoerg }
22267330f729Sjoerg
checkAvailabilityAttr(Sema & S,SourceRange Range,IdentifierInfo * Platform,VersionTuple Introduced,VersionTuple Deprecated,VersionTuple Obsoleted)22277330f729Sjoerg static bool checkAvailabilityAttr(Sema &S, SourceRange Range,
22287330f729Sjoerg IdentifierInfo *Platform,
22297330f729Sjoerg VersionTuple Introduced,
22307330f729Sjoerg VersionTuple Deprecated,
22317330f729Sjoerg VersionTuple Obsoleted) {
22327330f729Sjoerg StringRef PlatformName
22337330f729Sjoerg = AvailabilityAttr::getPrettyPlatformName(Platform->getName());
22347330f729Sjoerg if (PlatformName.empty())
22357330f729Sjoerg PlatformName = Platform->getName();
22367330f729Sjoerg
22377330f729Sjoerg // Ensure that Introduced <= Deprecated <= Obsoleted (although not all
22387330f729Sjoerg // of these steps are needed).
22397330f729Sjoerg if (!Introduced.empty() && !Deprecated.empty() &&
22407330f729Sjoerg !(Introduced <= Deprecated)) {
22417330f729Sjoerg S.Diag(Range.getBegin(), diag::warn_availability_version_ordering)
22427330f729Sjoerg << 1 << PlatformName << Deprecated.getAsString()
22437330f729Sjoerg << 0 << Introduced.getAsString();
22447330f729Sjoerg return true;
22457330f729Sjoerg }
22467330f729Sjoerg
22477330f729Sjoerg if (!Introduced.empty() && !Obsoleted.empty() &&
22487330f729Sjoerg !(Introduced <= Obsoleted)) {
22497330f729Sjoerg S.Diag(Range.getBegin(), diag::warn_availability_version_ordering)
22507330f729Sjoerg << 2 << PlatformName << Obsoleted.getAsString()
22517330f729Sjoerg << 0 << Introduced.getAsString();
22527330f729Sjoerg return true;
22537330f729Sjoerg }
22547330f729Sjoerg
22557330f729Sjoerg if (!Deprecated.empty() && !Obsoleted.empty() &&
22567330f729Sjoerg !(Deprecated <= Obsoleted)) {
22577330f729Sjoerg S.Diag(Range.getBegin(), diag::warn_availability_version_ordering)
22587330f729Sjoerg << 2 << PlatformName << Obsoleted.getAsString()
22597330f729Sjoerg << 1 << Deprecated.getAsString();
22607330f729Sjoerg return true;
22617330f729Sjoerg }
22627330f729Sjoerg
22637330f729Sjoerg return false;
22647330f729Sjoerg }
22657330f729Sjoerg
22667330f729Sjoerg /// Check whether the two versions match.
22677330f729Sjoerg ///
22687330f729Sjoerg /// If either version tuple is empty, then they are assumed to match. If
22697330f729Sjoerg /// \p BeforeIsOkay is true, then \p X can be less than or equal to \p Y.
versionsMatch(const VersionTuple & X,const VersionTuple & Y,bool BeforeIsOkay)22707330f729Sjoerg static bool versionsMatch(const VersionTuple &X, const VersionTuple &Y,
22717330f729Sjoerg bool BeforeIsOkay) {
22727330f729Sjoerg if (X.empty() || Y.empty())
22737330f729Sjoerg return true;
22747330f729Sjoerg
22757330f729Sjoerg if (X == Y)
22767330f729Sjoerg return true;
22777330f729Sjoerg
22787330f729Sjoerg if (BeforeIsOkay && X < Y)
22797330f729Sjoerg return true;
22807330f729Sjoerg
22817330f729Sjoerg return false;
22827330f729Sjoerg }
22837330f729Sjoerg
mergeAvailabilityAttr(NamedDecl * D,const AttributeCommonInfo & CI,IdentifierInfo * Platform,bool Implicit,VersionTuple Introduced,VersionTuple Deprecated,VersionTuple Obsoleted,bool IsUnavailable,StringRef Message,bool IsStrict,StringRef Replacement,AvailabilityMergeKind AMK,int Priority)22847330f729Sjoerg AvailabilityAttr *Sema::mergeAvailabilityAttr(
22857330f729Sjoerg NamedDecl *D, const AttributeCommonInfo &CI, IdentifierInfo *Platform,
22867330f729Sjoerg bool Implicit, VersionTuple Introduced, VersionTuple Deprecated,
22877330f729Sjoerg VersionTuple Obsoleted, bool IsUnavailable, StringRef Message,
22887330f729Sjoerg bool IsStrict, StringRef Replacement, AvailabilityMergeKind AMK,
22897330f729Sjoerg int Priority) {
22907330f729Sjoerg VersionTuple MergedIntroduced = Introduced;
22917330f729Sjoerg VersionTuple MergedDeprecated = Deprecated;
22927330f729Sjoerg VersionTuple MergedObsoleted = Obsoleted;
22937330f729Sjoerg bool FoundAny = false;
22947330f729Sjoerg bool OverrideOrImpl = false;
22957330f729Sjoerg switch (AMK) {
22967330f729Sjoerg case AMK_None:
22977330f729Sjoerg case AMK_Redeclaration:
22987330f729Sjoerg OverrideOrImpl = false;
22997330f729Sjoerg break;
23007330f729Sjoerg
23017330f729Sjoerg case AMK_Override:
23027330f729Sjoerg case AMK_ProtocolImplementation:
2303*e038c9c4Sjoerg case AMK_OptionalProtocolImplementation:
23047330f729Sjoerg OverrideOrImpl = true;
23057330f729Sjoerg break;
23067330f729Sjoerg }
23077330f729Sjoerg
23087330f729Sjoerg if (D->hasAttrs()) {
23097330f729Sjoerg AttrVec &Attrs = D->getAttrs();
23107330f729Sjoerg for (unsigned i = 0, e = Attrs.size(); i != e;) {
23117330f729Sjoerg const auto *OldAA = dyn_cast<AvailabilityAttr>(Attrs[i]);
23127330f729Sjoerg if (!OldAA) {
23137330f729Sjoerg ++i;
23147330f729Sjoerg continue;
23157330f729Sjoerg }
23167330f729Sjoerg
23177330f729Sjoerg IdentifierInfo *OldPlatform = OldAA->getPlatform();
23187330f729Sjoerg if (OldPlatform != Platform) {
23197330f729Sjoerg ++i;
23207330f729Sjoerg continue;
23217330f729Sjoerg }
23227330f729Sjoerg
23237330f729Sjoerg // If there is an existing availability attribute for this platform that
23247330f729Sjoerg // has a lower priority use the existing one and discard the new
23257330f729Sjoerg // attribute.
23267330f729Sjoerg if (OldAA->getPriority() < Priority)
23277330f729Sjoerg return nullptr;
23287330f729Sjoerg
23297330f729Sjoerg // If there is an existing attribute for this platform that has a higher
23307330f729Sjoerg // priority than the new attribute then erase the old one and continue
23317330f729Sjoerg // processing the attributes.
23327330f729Sjoerg if (OldAA->getPriority() > Priority) {
23337330f729Sjoerg Attrs.erase(Attrs.begin() + i);
23347330f729Sjoerg --e;
23357330f729Sjoerg continue;
23367330f729Sjoerg }
23377330f729Sjoerg
23387330f729Sjoerg FoundAny = true;
23397330f729Sjoerg VersionTuple OldIntroduced = OldAA->getIntroduced();
23407330f729Sjoerg VersionTuple OldDeprecated = OldAA->getDeprecated();
23417330f729Sjoerg VersionTuple OldObsoleted = OldAA->getObsoleted();
23427330f729Sjoerg bool OldIsUnavailable = OldAA->getUnavailable();
23437330f729Sjoerg
23447330f729Sjoerg if (!versionsMatch(OldIntroduced, Introduced, OverrideOrImpl) ||
23457330f729Sjoerg !versionsMatch(Deprecated, OldDeprecated, OverrideOrImpl) ||
23467330f729Sjoerg !versionsMatch(Obsoleted, OldObsoleted, OverrideOrImpl) ||
23477330f729Sjoerg !(OldIsUnavailable == IsUnavailable ||
23487330f729Sjoerg (OverrideOrImpl && !OldIsUnavailable && IsUnavailable))) {
23497330f729Sjoerg if (OverrideOrImpl) {
23507330f729Sjoerg int Which = -1;
23517330f729Sjoerg VersionTuple FirstVersion;
23527330f729Sjoerg VersionTuple SecondVersion;
23537330f729Sjoerg if (!versionsMatch(OldIntroduced, Introduced, OverrideOrImpl)) {
23547330f729Sjoerg Which = 0;
23557330f729Sjoerg FirstVersion = OldIntroduced;
23567330f729Sjoerg SecondVersion = Introduced;
23577330f729Sjoerg } else if (!versionsMatch(Deprecated, OldDeprecated, OverrideOrImpl)) {
23587330f729Sjoerg Which = 1;
23597330f729Sjoerg FirstVersion = Deprecated;
23607330f729Sjoerg SecondVersion = OldDeprecated;
23617330f729Sjoerg } else if (!versionsMatch(Obsoleted, OldObsoleted, OverrideOrImpl)) {
23627330f729Sjoerg Which = 2;
23637330f729Sjoerg FirstVersion = Obsoleted;
23647330f729Sjoerg SecondVersion = OldObsoleted;
23657330f729Sjoerg }
23667330f729Sjoerg
23677330f729Sjoerg if (Which == -1) {
23687330f729Sjoerg Diag(OldAA->getLocation(),
23697330f729Sjoerg diag::warn_mismatched_availability_override_unavail)
23707330f729Sjoerg << AvailabilityAttr::getPrettyPlatformName(Platform->getName())
23717330f729Sjoerg << (AMK == AMK_Override);
2372*e038c9c4Sjoerg } else if (Which != 1 && AMK == AMK_OptionalProtocolImplementation) {
2373*e038c9c4Sjoerg // Allow different 'introduced' / 'obsoleted' availability versions
2374*e038c9c4Sjoerg // on a method that implements an optional protocol requirement. It
2375*e038c9c4Sjoerg // makes less sense to allow this for 'deprecated' as the user can't
2376*e038c9c4Sjoerg // see if the method is 'deprecated' as 'respondsToSelector' will
2377*e038c9c4Sjoerg // still return true when the method is deprecated.
2378*e038c9c4Sjoerg ++i;
2379*e038c9c4Sjoerg continue;
23807330f729Sjoerg } else {
23817330f729Sjoerg Diag(OldAA->getLocation(),
23827330f729Sjoerg diag::warn_mismatched_availability_override)
23837330f729Sjoerg << Which
23847330f729Sjoerg << AvailabilityAttr::getPrettyPlatformName(Platform->getName())
23857330f729Sjoerg << FirstVersion.getAsString() << SecondVersion.getAsString()
23867330f729Sjoerg << (AMK == AMK_Override);
23877330f729Sjoerg }
23887330f729Sjoerg if (AMK == AMK_Override)
23897330f729Sjoerg Diag(CI.getLoc(), diag::note_overridden_method);
23907330f729Sjoerg else
23917330f729Sjoerg Diag(CI.getLoc(), diag::note_protocol_method);
23927330f729Sjoerg } else {
23937330f729Sjoerg Diag(OldAA->getLocation(), diag::warn_mismatched_availability);
23947330f729Sjoerg Diag(CI.getLoc(), diag::note_previous_attribute);
23957330f729Sjoerg }
23967330f729Sjoerg
23977330f729Sjoerg Attrs.erase(Attrs.begin() + i);
23987330f729Sjoerg --e;
23997330f729Sjoerg continue;
24007330f729Sjoerg }
24017330f729Sjoerg
24027330f729Sjoerg VersionTuple MergedIntroduced2 = MergedIntroduced;
24037330f729Sjoerg VersionTuple MergedDeprecated2 = MergedDeprecated;
24047330f729Sjoerg VersionTuple MergedObsoleted2 = MergedObsoleted;
24057330f729Sjoerg
24067330f729Sjoerg if (MergedIntroduced2.empty())
24077330f729Sjoerg MergedIntroduced2 = OldIntroduced;
24087330f729Sjoerg if (MergedDeprecated2.empty())
24097330f729Sjoerg MergedDeprecated2 = OldDeprecated;
24107330f729Sjoerg if (MergedObsoleted2.empty())
24117330f729Sjoerg MergedObsoleted2 = OldObsoleted;
24127330f729Sjoerg
24137330f729Sjoerg if (checkAvailabilityAttr(*this, OldAA->getRange(), Platform,
24147330f729Sjoerg MergedIntroduced2, MergedDeprecated2,
24157330f729Sjoerg MergedObsoleted2)) {
24167330f729Sjoerg Attrs.erase(Attrs.begin() + i);
24177330f729Sjoerg --e;
24187330f729Sjoerg continue;
24197330f729Sjoerg }
24207330f729Sjoerg
24217330f729Sjoerg MergedIntroduced = MergedIntroduced2;
24227330f729Sjoerg MergedDeprecated = MergedDeprecated2;
24237330f729Sjoerg MergedObsoleted = MergedObsoleted2;
24247330f729Sjoerg ++i;
24257330f729Sjoerg }
24267330f729Sjoerg }
24277330f729Sjoerg
24287330f729Sjoerg if (FoundAny &&
24297330f729Sjoerg MergedIntroduced == Introduced &&
24307330f729Sjoerg MergedDeprecated == Deprecated &&
24317330f729Sjoerg MergedObsoleted == Obsoleted)
24327330f729Sjoerg return nullptr;
24337330f729Sjoerg
24347330f729Sjoerg // Only create a new attribute if !OverrideOrImpl, but we want to do
24357330f729Sjoerg // the checking.
24367330f729Sjoerg if (!checkAvailabilityAttr(*this, CI.getRange(), Platform, MergedIntroduced,
24377330f729Sjoerg MergedDeprecated, MergedObsoleted) &&
24387330f729Sjoerg !OverrideOrImpl) {
24397330f729Sjoerg auto *Avail = ::new (Context) AvailabilityAttr(
24407330f729Sjoerg Context, CI, Platform, Introduced, Deprecated, Obsoleted, IsUnavailable,
24417330f729Sjoerg Message, IsStrict, Replacement, Priority);
24427330f729Sjoerg Avail->setImplicit(Implicit);
24437330f729Sjoerg return Avail;
24447330f729Sjoerg }
24457330f729Sjoerg return nullptr;
24467330f729Sjoerg }
24477330f729Sjoerg
handleAvailabilityAttr(Sema & S,Decl * D,const ParsedAttr & AL)24487330f729Sjoerg static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
2449*e038c9c4Sjoerg if (!AL.checkExactlyNumArgs(S, 1))
24507330f729Sjoerg return;
24517330f729Sjoerg IdentifierLoc *Platform = AL.getArgAsIdent(0);
24527330f729Sjoerg
24537330f729Sjoerg IdentifierInfo *II = Platform->Ident;
24547330f729Sjoerg if (AvailabilityAttr::getPrettyPlatformName(II->getName()).empty())
24557330f729Sjoerg S.Diag(Platform->Loc, diag::warn_availability_unknown_platform)
24567330f729Sjoerg << Platform->Ident;
24577330f729Sjoerg
24587330f729Sjoerg auto *ND = dyn_cast<NamedDecl>(D);
24597330f729Sjoerg if (!ND) // We warned about this already, so just return.
24607330f729Sjoerg return;
24617330f729Sjoerg
24627330f729Sjoerg AvailabilityChange Introduced = AL.getAvailabilityIntroduced();
24637330f729Sjoerg AvailabilityChange Deprecated = AL.getAvailabilityDeprecated();
24647330f729Sjoerg AvailabilityChange Obsoleted = AL.getAvailabilityObsoleted();
24657330f729Sjoerg bool IsUnavailable = AL.getUnavailableLoc().isValid();
24667330f729Sjoerg bool IsStrict = AL.getStrictLoc().isValid();
24677330f729Sjoerg StringRef Str;
24687330f729Sjoerg if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getMessageExpr()))
24697330f729Sjoerg Str = SE->getString();
24707330f729Sjoerg StringRef Replacement;
24717330f729Sjoerg if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getReplacementExpr()))
24727330f729Sjoerg Replacement = SE->getString();
24737330f729Sjoerg
24747330f729Sjoerg if (II->isStr("swift")) {
24757330f729Sjoerg if (Introduced.isValid() || Obsoleted.isValid() ||
24767330f729Sjoerg (!IsUnavailable && !Deprecated.isValid())) {
24777330f729Sjoerg S.Diag(AL.getLoc(),
24787330f729Sjoerg diag::warn_availability_swift_unavailable_deprecated_only);
24797330f729Sjoerg return;
24807330f729Sjoerg }
24817330f729Sjoerg }
24827330f729Sjoerg
24837330f729Sjoerg int PriorityModifier = AL.isPragmaClangAttribute()
24847330f729Sjoerg ? Sema::AP_PragmaClangAttribute
24857330f729Sjoerg : Sema::AP_Explicit;
24867330f729Sjoerg AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(
24877330f729Sjoerg ND, AL, II, false /*Implicit*/, Introduced.Version, Deprecated.Version,
24887330f729Sjoerg Obsoleted.Version, IsUnavailable, Str, IsStrict, Replacement,
24897330f729Sjoerg Sema::AMK_None, PriorityModifier);
24907330f729Sjoerg if (NewAttr)
24917330f729Sjoerg D->addAttr(NewAttr);
24927330f729Sjoerg
24937330f729Sjoerg // Transcribe "ios" to "watchos" (and add a new attribute) if the versioning
24947330f729Sjoerg // matches before the start of the watchOS platform.
24957330f729Sjoerg if (S.Context.getTargetInfo().getTriple().isWatchOS()) {
24967330f729Sjoerg IdentifierInfo *NewII = nullptr;
24977330f729Sjoerg if (II->getName() == "ios")
24987330f729Sjoerg NewII = &S.Context.Idents.get("watchos");
24997330f729Sjoerg else if (II->getName() == "ios_app_extension")
25007330f729Sjoerg NewII = &S.Context.Idents.get("watchos_app_extension");
25017330f729Sjoerg
25027330f729Sjoerg if (NewII) {
25037330f729Sjoerg auto adjustWatchOSVersion = [](VersionTuple Version) -> VersionTuple {
25047330f729Sjoerg if (Version.empty())
25057330f729Sjoerg return Version;
25067330f729Sjoerg auto Major = Version.getMajor();
25077330f729Sjoerg auto NewMajor = Major >= 9 ? Major - 7 : 0;
25087330f729Sjoerg if (NewMajor >= 2) {
25097330f729Sjoerg if (Version.getMinor().hasValue()) {
25107330f729Sjoerg if (Version.getSubminor().hasValue())
25117330f729Sjoerg return VersionTuple(NewMajor, Version.getMinor().getValue(),
25127330f729Sjoerg Version.getSubminor().getValue());
25137330f729Sjoerg else
25147330f729Sjoerg return VersionTuple(NewMajor, Version.getMinor().getValue());
25157330f729Sjoerg }
25167330f729Sjoerg return VersionTuple(NewMajor);
25177330f729Sjoerg }
25187330f729Sjoerg
25197330f729Sjoerg return VersionTuple(2, 0);
25207330f729Sjoerg };
25217330f729Sjoerg
25227330f729Sjoerg auto NewIntroduced = adjustWatchOSVersion(Introduced.Version);
25237330f729Sjoerg auto NewDeprecated = adjustWatchOSVersion(Deprecated.Version);
25247330f729Sjoerg auto NewObsoleted = adjustWatchOSVersion(Obsoleted.Version);
25257330f729Sjoerg
25267330f729Sjoerg AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(
25277330f729Sjoerg ND, AL, NewII, true /*Implicit*/, NewIntroduced, NewDeprecated,
25287330f729Sjoerg NewObsoleted, IsUnavailable, Str, IsStrict, Replacement,
25297330f729Sjoerg Sema::AMK_None,
25307330f729Sjoerg PriorityModifier + Sema::AP_InferredFromOtherPlatform);
25317330f729Sjoerg if (NewAttr)
25327330f729Sjoerg D->addAttr(NewAttr);
25337330f729Sjoerg }
25347330f729Sjoerg } else if (S.Context.getTargetInfo().getTriple().isTvOS()) {
25357330f729Sjoerg // Transcribe "ios" to "tvos" (and add a new attribute) if the versioning
25367330f729Sjoerg // matches before the start of the tvOS platform.
25377330f729Sjoerg IdentifierInfo *NewII = nullptr;
25387330f729Sjoerg if (II->getName() == "ios")
25397330f729Sjoerg NewII = &S.Context.Idents.get("tvos");
25407330f729Sjoerg else if (II->getName() == "ios_app_extension")
25417330f729Sjoerg NewII = &S.Context.Idents.get("tvos_app_extension");
25427330f729Sjoerg
25437330f729Sjoerg if (NewII) {
25447330f729Sjoerg AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(
25457330f729Sjoerg ND, AL, NewII, true /*Implicit*/, Introduced.Version,
25467330f729Sjoerg Deprecated.Version, Obsoleted.Version, IsUnavailable, Str, IsStrict,
25477330f729Sjoerg Replacement, Sema::AMK_None,
25487330f729Sjoerg PriorityModifier + Sema::AP_InferredFromOtherPlatform);
25497330f729Sjoerg if (NewAttr)
25507330f729Sjoerg D->addAttr(NewAttr);
25517330f729Sjoerg }
25527330f729Sjoerg }
25537330f729Sjoerg }
25547330f729Sjoerg
handleExternalSourceSymbolAttr(Sema & S,Decl * D,const ParsedAttr & AL)25557330f729Sjoerg static void handleExternalSourceSymbolAttr(Sema &S, Decl *D,
25567330f729Sjoerg const ParsedAttr &AL) {
2557*e038c9c4Sjoerg if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 3))
25587330f729Sjoerg return;
25597330f729Sjoerg
25607330f729Sjoerg StringRef Language;
25617330f729Sjoerg if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getArgAsExpr(0)))
25627330f729Sjoerg Language = SE->getString();
25637330f729Sjoerg StringRef DefinedIn;
25647330f729Sjoerg if (const auto *SE = dyn_cast_or_null<StringLiteral>(AL.getArgAsExpr(1)))
25657330f729Sjoerg DefinedIn = SE->getString();
25667330f729Sjoerg bool IsGeneratedDeclaration = AL.getArgAsIdent(2) != nullptr;
25677330f729Sjoerg
25687330f729Sjoerg D->addAttr(::new (S.Context) ExternalSourceSymbolAttr(
25697330f729Sjoerg S.Context, AL, Language, DefinedIn, IsGeneratedDeclaration));
25707330f729Sjoerg }
25717330f729Sjoerg
25727330f729Sjoerg template <class T>
mergeVisibilityAttr(Sema & S,Decl * D,const AttributeCommonInfo & CI,typename T::VisibilityType value)25737330f729Sjoerg static T *mergeVisibilityAttr(Sema &S, Decl *D, const AttributeCommonInfo &CI,
25747330f729Sjoerg typename T::VisibilityType value) {
25757330f729Sjoerg T *existingAttr = D->getAttr<T>();
25767330f729Sjoerg if (existingAttr) {
25777330f729Sjoerg typename T::VisibilityType existingValue = existingAttr->getVisibility();
25787330f729Sjoerg if (existingValue == value)
25797330f729Sjoerg return nullptr;
25807330f729Sjoerg S.Diag(existingAttr->getLocation(), diag::err_mismatched_visibility);
25817330f729Sjoerg S.Diag(CI.getLoc(), diag::note_previous_attribute);
25827330f729Sjoerg D->dropAttr<T>();
25837330f729Sjoerg }
25847330f729Sjoerg return ::new (S.Context) T(S.Context, CI, value);
25857330f729Sjoerg }
25867330f729Sjoerg
mergeVisibilityAttr(Decl * D,const AttributeCommonInfo & CI,VisibilityAttr::VisibilityType Vis)25877330f729Sjoerg VisibilityAttr *Sema::mergeVisibilityAttr(Decl *D,
25887330f729Sjoerg const AttributeCommonInfo &CI,
25897330f729Sjoerg VisibilityAttr::VisibilityType Vis) {
25907330f729Sjoerg return ::mergeVisibilityAttr<VisibilityAttr>(*this, D, CI, Vis);
25917330f729Sjoerg }
25927330f729Sjoerg
25937330f729Sjoerg TypeVisibilityAttr *
mergeTypeVisibilityAttr(Decl * D,const AttributeCommonInfo & CI,TypeVisibilityAttr::VisibilityType Vis)25947330f729Sjoerg Sema::mergeTypeVisibilityAttr(Decl *D, const AttributeCommonInfo &CI,
25957330f729Sjoerg TypeVisibilityAttr::VisibilityType Vis) {
25967330f729Sjoerg return ::mergeVisibilityAttr<TypeVisibilityAttr>(*this, D, CI, Vis);
25977330f729Sjoerg }
25987330f729Sjoerg
handleVisibilityAttr(Sema & S,Decl * D,const ParsedAttr & AL,bool isTypeVisibility)25997330f729Sjoerg static void handleVisibilityAttr(Sema &S, Decl *D, const ParsedAttr &AL,
26007330f729Sjoerg bool isTypeVisibility) {
26017330f729Sjoerg // Visibility attributes don't mean anything on a typedef.
26027330f729Sjoerg if (isa<TypedefNameDecl>(D)) {
26037330f729Sjoerg S.Diag(AL.getRange().getBegin(), diag::warn_attribute_ignored) << AL;
26047330f729Sjoerg return;
26057330f729Sjoerg }
26067330f729Sjoerg
26077330f729Sjoerg // 'type_visibility' can only go on a type or namespace.
26087330f729Sjoerg if (isTypeVisibility &&
26097330f729Sjoerg !(isa<TagDecl>(D) ||
26107330f729Sjoerg isa<ObjCInterfaceDecl>(D) ||
26117330f729Sjoerg isa<NamespaceDecl>(D))) {
26127330f729Sjoerg S.Diag(AL.getRange().getBegin(), diag::err_attribute_wrong_decl_type)
26137330f729Sjoerg << AL << ExpectedTypeOrNamespace;
26147330f729Sjoerg return;
26157330f729Sjoerg }
26167330f729Sjoerg
26177330f729Sjoerg // Check that the argument is a string literal.
26187330f729Sjoerg StringRef TypeStr;
26197330f729Sjoerg SourceLocation LiteralLoc;
26207330f729Sjoerg if (!S.checkStringLiteralArgumentAttr(AL, 0, TypeStr, &LiteralLoc))
26217330f729Sjoerg return;
26227330f729Sjoerg
26237330f729Sjoerg VisibilityAttr::VisibilityType type;
26247330f729Sjoerg if (!VisibilityAttr::ConvertStrToVisibilityType(TypeStr, type)) {
26257330f729Sjoerg S.Diag(LiteralLoc, diag::warn_attribute_type_not_supported) << AL
26267330f729Sjoerg << TypeStr;
26277330f729Sjoerg return;
26287330f729Sjoerg }
26297330f729Sjoerg
26307330f729Sjoerg // Complain about attempts to use protected visibility on targets
26317330f729Sjoerg // (like Darwin) that don't support it.
26327330f729Sjoerg if (type == VisibilityAttr::Protected &&
26337330f729Sjoerg !S.Context.getTargetInfo().hasProtectedVisibility()) {
26347330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_protected_visibility);
26357330f729Sjoerg type = VisibilityAttr::Default;
26367330f729Sjoerg }
26377330f729Sjoerg
26387330f729Sjoerg Attr *newAttr;
26397330f729Sjoerg if (isTypeVisibility) {
26407330f729Sjoerg newAttr = S.mergeTypeVisibilityAttr(
26417330f729Sjoerg D, AL, (TypeVisibilityAttr::VisibilityType)type);
26427330f729Sjoerg } else {
26437330f729Sjoerg newAttr = S.mergeVisibilityAttr(D, AL, type);
26447330f729Sjoerg }
26457330f729Sjoerg if (newAttr)
26467330f729Sjoerg D->addAttr(newAttr);
26477330f729Sjoerg }
26487330f729Sjoerg
handleObjCDirectAttr(Sema & S,Decl * D,const ParsedAttr & AL)2649*e038c9c4Sjoerg static void handleObjCDirectAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
2650*e038c9c4Sjoerg // objc_direct cannot be set on methods declared in the context of a protocol
2651*e038c9c4Sjoerg if (isa<ObjCProtocolDecl>(D->getDeclContext())) {
2652*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::err_objc_direct_on_protocol) << false;
2653*e038c9c4Sjoerg return;
2654*e038c9c4Sjoerg }
2655*e038c9c4Sjoerg
2656*e038c9c4Sjoerg if (S.getLangOpts().ObjCRuntime.allowsDirectDispatch()) {
2657*e038c9c4Sjoerg handleSimpleAttribute<ObjCDirectAttr>(S, D, AL);
2658*e038c9c4Sjoerg } else {
2659*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::warn_objc_direct_ignored) << AL;
2660*e038c9c4Sjoerg }
2661*e038c9c4Sjoerg }
2662*e038c9c4Sjoerg
handleObjCDirectMembersAttr(Sema & S,Decl * D,const ParsedAttr & AL)2663*e038c9c4Sjoerg static void handleObjCDirectMembersAttr(Sema &S, Decl *D,
2664*e038c9c4Sjoerg const ParsedAttr &AL) {
2665*e038c9c4Sjoerg if (S.getLangOpts().ObjCRuntime.allowsDirectDispatch()) {
2666*e038c9c4Sjoerg handleSimpleAttribute<ObjCDirectMembersAttr>(S, D, AL);
2667*e038c9c4Sjoerg } else {
2668*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::warn_objc_direct_ignored) << AL;
2669*e038c9c4Sjoerg }
2670*e038c9c4Sjoerg }
2671*e038c9c4Sjoerg
handleObjCMethodFamilyAttr(Sema & S,Decl * D,const ParsedAttr & AL)26727330f729Sjoerg static void handleObjCMethodFamilyAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
26737330f729Sjoerg const auto *M = cast<ObjCMethodDecl>(D);
26747330f729Sjoerg if (!AL.isArgIdent(0)) {
26757330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
26767330f729Sjoerg << AL << 1 << AANT_ArgumentIdentifier;
26777330f729Sjoerg return;
26787330f729Sjoerg }
26797330f729Sjoerg
26807330f729Sjoerg IdentifierLoc *IL = AL.getArgAsIdent(0);
26817330f729Sjoerg ObjCMethodFamilyAttr::FamilyKind F;
26827330f729Sjoerg if (!ObjCMethodFamilyAttr::ConvertStrToFamilyKind(IL->Ident->getName(), F)) {
26837330f729Sjoerg S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << AL << IL->Ident;
26847330f729Sjoerg return;
26857330f729Sjoerg }
26867330f729Sjoerg
26877330f729Sjoerg if (F == ObjCMethodFamilyAttr::OMF_init &&
26887330f729Sjoerg !M->getReturnType()->isObjCObjectPointerType()) {
26897330f729Sjoerg S.Diag(M->getLocation(), diag::err_init_method_bad_return_type)
26907330f729Sjoerg << M->getReturnType();
26917330f729Sjoerg // Ignore the attribute.
26927330f729Sjoerg return;
26937330f729Sjoerg }
26947330f729Sjoerg
26957330f729Sjoerg D->addAttr(new (S.Context) ObjCMethodFamilyAttr(S.Context, AL, F));
26967330f729Sjoerg }
26977330f729Sjoerg
handleObjCNSObject(Sema & S,Decl * D,const ParsedAttr & AL)26987330f729Sjoerg static void handleObjCNSObject(Sema &S, Decl *D, const ParsedAttr &AL) {
26997330f729Sjoerg if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) {
27007330f729Sjoerg QualType T = TD->getUnderlyingType();
27017330f729Sjoerg if (!T->isCARCBridgableType()) {
27027330f729Sjoerg S.Diag(TD->getLocation(), diag::err_nsobject_attribute);
27037330f729Sjoerg return;
27047330f729Sjoerg }
27057330f729Sjoerg }
27067330f729Sjoerg else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) {
27077330f729Sjoerg QualType T = PD->getType();
27087330f729Sjoerg if (!T->isCARCBridgableType()) {
27097330f729Sjoerg S.Diag(PD->getLocation(), diag::err_nsobject_attribute);
27107330f729Sjoerg return;
27117330f729Sjoerg }
27127330f729Sjoerg }
27137330f729Sjoerg else {
27147330f729Sjoerg // It is okay to include this attribute on properties, e.g.:
27157330f729Sjoerg //
27167330f729Sjoerg // @property (retain, nonatomic) struct Bork *Q __attribute__((NSObject));
27177330f729Sjoerg //
27187330f729Sjoerg // In this case it follows tradition and suppresses an error in the above
27197330f729Sjoerg // case.
27207330f729Sjoerg S.Diag(D->getLocation(), diag::warn_nsobject_attribute);
27217330f729Sjoerg }
27227330f729Sjoerg D->addAttr(::new (S.Context) ObjCNSObjectAttr(S.Context, AL));
27237330f729Sjoerg }
27247330f729Sjoerg
handleObjCIndependentClass(Sema & S,Decl * D,const ParsedAttr & AL)27257330f729Sjoerg static void handleObjCIndependentClass(Sema &S, Decl *D, const ParsedAttr &AL) {
27267330f729Sjoerg if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) {
27277330f729Sjoerg QualType T = TD->getUnderlyingType();
27287330f729Sjoerg if (!T->isObjCObjectPointerType()) {
27297330f729Sjoerg S.Diag(TD->getLocation(), diag::warn_ptr_independentclass_attribute);
27307330f729Sjoerg return;
27317330f729Sjoerg }
27327330f729Sjoerg } else {
27337330f729Sjoerg S.Diag(D->getLocation(), diag::warn_independentclass_attribute);
27347330f729Sjoerg return;
27357330f729Sjoerg }
27367330f729Sjoerg D->addAttr(::new (S.Context) ObjCIndependentClassAttr(S.Context, AL));
27377330f729Sjoerg }
27387330f729Sjoerg
handleBlocksAttr(Sema & S,Decl * D,const ParsedAttr & AL)27397330f729Sjoerg static void handleBlocksAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
27407330f729Sjoerg if (!AL.isArgIdent(0)) {
27417330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
27427330f729Sjoerg << AL << 1 << AANT_ArgumentIdentifier;
27437330f729Sjoerg return;
27447330f729Sjoerg }
27457330f729Sjoerg
27467330f729Sjoerg IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
27477330f729Sjoerg BlocksAttr::BlockType type;
27487330f729Sjoerg if (!BlocksAttr::ConvertStrToBlockType(II->getName(), type)) {
27497330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II;
27507330f729Sjoerg return;
27517330f729Sjoerg }
27527330f729Sjoerg
27537330f729Sjoerg D->addAttr(::new (S.Context) BlocksAttr(S.Context, AL, type));
27547330f729Sjoerg }
27557330f729Sjoerg
handleSentinelAttr(Sema & S,Decl * D,const ParsedAttr & AL)27567330f729Sjoerg static void handleSentinelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
27577330f729Sjoerg unsigned sentinel = (unsigned)SentinelAttr::DefaultSentinel;
27587330f729Sjoerg if (AL.getNumArgs() > 0) {
27597330f729Sjoerg Expr *E = AL.getArgAsExpr(0);
2760*e038c9c4Sjoerg Optional<llvm::APSInt> Idx = llvm::APSInt(32);
27617330f729Sjoerg if (E->isTypeDependent() || E->isValueDependent() ||
2762*e038c9c4Sjoerg !(Idx = E->getIntegerConstantExpr(S.Context))) {
27637330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
27647330f729Sjoerg << AL << 1 << AANT_ArgumentIntegerConstant << E->getSourceRange();
27657330f729Sjoerg return;
27667330f729Sjoerg }
27677330f729Sjoerg
2768*e038c9c4Sjoerg if (Idx->isSigned() && Idx->isNegative()) {
27697330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_sentinel_less_than_zero)
27707330f729Sjoerg << E->getSourceRange();
27717330f729Sjoerg return;
27727330f729Sjoerg }
27737330f729Sjoerg
2774*e038c9c4Sjoerg sentinel = Idx->getZExtValue();
27757330f729Sjoerg }
27767330f729Sjoerg
27777330f729Sjoerg unsigned nullPos = (unsigned)SentinelAttr::DefaultNullPos;
27787330f729Sjoerg if (AL.getNumArgs() > 1) {
27797330f729Sjoerg Expr *E = AL.getArgAsExpr(1);
2780*e038c9c4Sjoerg Optional<llvm::APSInt> Idx = llvm::APSInt(32);
27817330f729Sjoerg if (E->isTypeDependent() || E->isValueDependent() ||
2782*e038c9c4Sjoerg !(Idx = E->getIntegerConstantExpr(S.Context))) {
27837330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
27847330f729Sjoerg << AL << 2 << AANT_ArgumentIntegerConstant << E->getSourceRange();
27857330f729Sjoerg return;
27867330f729Sjoerg }
2787*e038c9c4Sjoerg nullPos = Idx->getZExtValue();
27887330f729Sjoerg
2789*e038c9c4Sjoerg if ((Idx->isSigned() && Idx->isNegative()) || nullPos > 1) {
27907330f729Sjoerg // FIXME: This error message could be improved, it would be nice
27917330f729Sjoerg // to say what the bounds actually are.
27927330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_sentinel_not_zero_or_one)
27937330f729Sjoerg << E->getSourceRange();
27947330f729Sjoerg return;
27957330f729Sjoerg }
27967330f729Sjoerg }
27977330f729Sjoerg
27987330f729Sjoerg if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
27997330f729Sjoerg const FunctionType *FT = FD->getType()->castAs<FunctionType>();
28007330f729Sjoerg if (isa<FunctionNoProtoType>(FT)) {
28017330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_named_arguments);
28027330f729Sjoerg return;
28037330f729Sjoerg }
28047330f729Sjoerg
28057330f729Sjoerg if (!cast<FunctionProtoType>(FT)->isVariadic()) {
28067330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0;
28077330f729Sjoerg return;
28087330f729Sjoerg }
28097330f729Sjoerg } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
28107330f729Sjoerg if (!MD->isVariadic()) {
28117330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0;
28127330f729Sjoerg return;
28137330f729Sjoerg }
28147330f729Sjoerg } else if (const auto *BD = dyn_cast<BlockDecl>(D)) {
28157330f729Sjoerg if (!BD->isVariadic()) {
28167330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 1;
28177330f729Sjoerg return;
28187330f729Sjoerg }
28197330f729Sjoerg } else if (const auto *V = dyn_cast<VarDecl>(D)) {
28207330f729Sjoerg QualType Ty = V->getType();
28217330f729Sjoerg if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) {
28227330f729Sjoerg const FunctionType *FT = Ty->isFunctionPointerType()
28237330f729Sjoerg ? D->getFunctionType()
2824*e038c9c4Sjoerg : Ty->castAs<BlockPointerType>()
2825*e038c9c4Sjoerg ->getPointeeType()
2826*e038c9c4Sjoerg ->castAs<FunctionType>();
28277330f729Sjoerg if (!cast<FunctionProtoType>(FT)->isVariadic()) {
28287330f729Sjoerg int m = Ty->isFunctionPointerType() ? 0 : 1;
28297330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_sentinel_not_variadic) << m;
28307330f729Sjoerg return;
28317330f729Sjoerg }
28327330f729Sjoerg } else {
28337330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
28347330f729Sjoerg << AL << ExpectedFunctionMethodOrBlock;
28357330f729Sjoerg return;
28367330f729Sjoerg }
28377330f729Sjoerg } else {
28387330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
28397330f729Sjoerg << AL << ExpectedFunctionMethodOrBlock;
28407330f729Sjoerg return;
28417330f729Sjoerg }
28427330f729Sjoerg D->addAttr(::new (S.Context) SentinelAttr(S.Context, AL, sentinel, nullPos));
28437330f729Sjoerg }
28447330f729Sjoerg
handleWarnUnusedResult(Sema & S,Decl * D,const ParsedAttr & AL)28457330f729Sjoerg static void handleWarnUnusedResult(Sema &S, Decl *D, const ParsedAttr &AL) {
28467330f729Sjoerg if (D->getFunctionType() &&
28477330f729Sjoerg D->getFunctionType()->getReturnType()->isVoidType() &&
28487330f729Sjoerg !isa<CXXConstructorDecl>(D)) {
28497330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_void_function_method) << AL << 0;
28507330f729Sjoerg return;
28517330f729Sjoerg }
28527330f729Sjoerg if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
28537330f729Sjoerg if (MD->getReturnType()->isVoidType()) {
28547330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_void_function_method) << AL << 1;
28557330f729Sjoerg return;
28567330f729Sjoerg }
28577330f729Sjoerg
28587330f729Sjoerg StringRef Str;
28597330f729Sjoerg if ((AL.isCXX11Attribute() || AL.isC2xAttribute()) && !AL.getScopeName()) {
2860*e038c9c4Sjoerg // The standard attribute cannot be applied to variable declarations such
2861*e038c9c4Sjoerg // as a function pointer.
2862*e038c9c4Sjoerg if (isa<VarDecl>(D))
2863*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type_str)
2864*e038c9c4Sjoerg << AL << "functions, classes, or enumerations";
2865*e038c9c4Sjoerg
28667330f729Sjoerg // If this is spelled as the standard C++17 attribute, but not in C++17,
28677330f729Sjoerg // warn about using it as an extension. If there are attribute arguments,
28687330f729Sjoerg // then claim it's a C++2a extension instead.
28697330f729Sjoerg // FIXME: If WG14 does not seem likely to adopt the same feature, add an
28707330f729Sjoerg // extension warning for C2x mode.
28717330f729Sjoerg const LangOptions &LO = S.getLangOpts();
28727330f729Sjoerg if (AL.getNumArgs() == 1) {
2873*e038c9c4Sjoerg if (LO.CPlusPlus && !LO.CPlusPlus20)
2874*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::ext_cxx20_attr) << AL;
28757330f729Sjoerg
28767330f729Sjoerg // Since this this is spelled [[nodiscard]], get the optional string
28777330f729Sjoerg // literal. If in C++ mode, but not in C++2a mode, diagnose as an
28787330f729Sjoerg // extension.
28797330f729Sjoerg // FIXME: C2x should support this feature as well, even as an extension.
28807330f729Sjoerg if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, nullptr))
28817330f729Sjoerg return;
28827330f729Sjoerg } else if (LO.CPlusPlus && !LO.CPlusPlus17)
28837330f729Sjoerg S.Diag(AL.getLoc(), diag::ext_cxx17_attr) << AL;
28847330f729Sjoerg }
28857330f729Sjoerg
28867330f729Sjoerg D->addAttr(::new (S.Context) WarnUnusedResultAttr(S.Context, AL, Str));
28877330f729Sjoerg }
28887330f729Sjoerg
handleWeakImportAttr(Sema & S,Decl * D,const ParsedAttr & AL)28897330f729Sjoerg static void handleWeakImportAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
28907330f729Sjoerg // weak_import only applies to variable & function declarations.
28917330f729Sjoerg bool isDef = false;
28927330f729Sjoerg if (!D->canBeWeakImported(isDef)) {
28937330f729Sjoerg if (isDef)
28947330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_invalid_on_definition)
28957330f729Sjoerg << "weak_import";
28967330f729Sjoerg else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D) ||
28977330f729Sjoerg (S.Context.getTargetInfo().getTriple().isOSDarwin() &&
28987330f729Sjoerg (isa<ObjCInterfaceDecl>(D) || isa<EnumDecl>(D)))) {
28997330f729Sjoerg // Nothing to warn about here.
29007330f729Sjoerg } else
29017330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
29027330f729Sjoerg << AL << ExpectedVariableOrFunction;
29037330f729Sjoerg
29047330f729Sjoerg return;
29057330f729Sjoerg }
29067330f729Sjoerg
29077330f729Sjoerg D->addAttr(::new (S.Context) WeakImportAttr(S.Context, AL));
29087330f729Sjoerg }
29097330f729Sjoerg
29107330f729Sjoerg // Handles reqd_work_group_size and work_group_size_hint.
29117330f729Sjoerg template <typename WorkGroupAttr>
handleWorkGroupSize(Sema & S,Decl * D,const ParsedAttr & AL)29127330f729Sjoerg static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) {
29137330f729Sjoerg uint32_t WGSize[3];
29147330f729Sjoerg for (unsigned i = 0; i < 3; ++i) {
29157330f729Sjoerg const Expr *E = AL.getArgAsExpr(i);
29167330f729Sjoerg if (!checkUInt32Argument(S, AL, E, WGSize[i], i,
29177330f729Sjoerg /*StrictlyUnsigned=*/true))
29187330f729Sjoerg return;
29197330f729Sjoerg if (WGSize[i] == 0) {
29207330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_is_zero)
29217330f729Sjoerg << AL << E->getSourceRange();
29227330f729Sjoerg return;
29237330f729Sjoerg }
29247330f729Sjoerg }
29257330f729Sjoerg
29267330f729Sjoerg WorkGroupAttr *Existing = D->getAttr<WorkGroupAttr>();
29277330f729Sjoerg if (Existing && !(Existing->getXDim() == WGSize[0] &&
29287330f729Sjoerg Existing->getYDim() == WGSize[1] &&
29297330f729Sjoerg Existing->getZDim() == WGSize[2]))
29307330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
29317330f729Sjoerg
29327330f729Sjoerg D->addAttr(::new (S.Context)
29337330f729Sjoerg WorkGroupAttr(S.Context, AL, WGSize[0], WGSize[1], WGSize[2]));
29347330f729Sjoerg }
29357330f729Sjoerg
29367330f729Sjoerg // Handles intel_reqd_sub_group_size.
handleSubGroupSize(Sema & S,Decl * D,const ParsedAttr & AL)29377330f729Sjoerg static void handleSubGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) {
29387330f729Sjoerg uint32_t SGSize;
29397330f729Sjoerg const Expr *E = AL.getArgAsExpr(0);
29407330f729Sjoerg if (!checkUInt32Argument(S, AL, E, SGSize))
29417330f729Sjoerg return;
29427330f729Sjoerg if (SGSize == 0) {
29437330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_is_zero)
29447330f729Sjoerg << AL << E->getSourceRange();
29457330f729Sjoerg return;
29467330f729Sjoerg }
29477330f729Sjoerg
29487330f729Sjoerg OpenCLIntelReqdSubGroupSizeAttr *Existing =
29497330f729Sjoerg D->getAttr<OpenCLIntelReqdSubGroupSizeAttr>();
29507330f729Sjoerg if (Existing && Existing->getSubGroupSize() != SGSize)
29517330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
29527330f729Sjoerg
29537330f729Sjoerg D->addAttr(::new (S.Context)
29547330f729Sjoerg OpenCLIntelReqdSubGroupSizeAttr(S.Context, AL, SGSize));
29557330f729Sjoerg }
29567330f729Sjoerg
handleVecTypeHint(Sema & S,Decl * D,const ParsedAttr & AL)29577330f729Sjoerg static void handleVecTypeHint(Sema &S, Decl *D, const ParsedAttr &AL) {
29587330f729Sjoerg if (!AL.hasParsedType()) {
29597330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
29607330f729Sjoerg return;
29617330f729Sjoerg }
29627330f729Sjoerg
29637330f729Sjoerg TypeSourceInfo *ParmTSI = nullptr;
29647330f729Sjoerg QualType ParmType = S.GetTypeFromParser(AL.getTypeArg(), &ParmTSI);
29657330f729Sjoerg assert(ParmTSI && "no type source info for attribute argument");
29667330f729Sjoerg
29677330f729Sjoerg if (!ParmType->isExtVectorType() && !ParmType->isFloatingType() &&
29687330f729Sjoerg (ParmType->isBooleanType() ||
29697330f729Sjoerg !ParmType->isIntegralType(S.getASTContext()))) {
2970*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_invalid_argument) << 2 << AL;
29717330f729Sjoerg return;
29727330f729Sjoerg }
29737330f729Sjoerg
29747330f729Sjoerg if (VecTypeHintAttr *A = D->getAttr<VecTypeHintAttr>()) {
29757330f729Sjoerg if (!S.Context.hasSameType(A->getTypeHint(), ParmType)) {
29767330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
29777330f729Sjoerg return;
29787330f729Sjoerg }
29797330f729Sjoerg }
29807330f729Sjoerg
29817330f729Sjoerg D->addAttr(::new (S.Context) VecTypeHintAttr(S.Context, AL, ParmTSI));
29827330f729Sjoerg }
29837330f729Sjoerg
mergeSectionAttr(Decl * D,const AttributeCommonInfo & CI,StringRef Name)29847330f729Sjoerg SectionAttr *Sema::mergeSectionAttr(Decl *D, const AttributeCommonInfo &CI,
29857330f729Sjoerg StringRef Name) {
29867330f729Sjoerg // Explicit or partial specializations do not inherit
29877330f729Sjoerg // the section attribute from the primary template.
29887330f729Sjoerg if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
29897330f729Sjoerg if (CI.getAttributeSpellingListIndex() == SectionAttr::Declspec_allocate &&
29907330f729Sjoerg FD->isFunctionTemplateSpecialization())
29917330f729Sjoerg return nullptr;
29927330f729Sjoerg }
29937330f729Sjoerg if (SectionAttr *ExistingAttr = D->getAttr<SectionAttr>()) {
29947330f729Sjoerg if (ExistingAttr->getName() == Name)
29957330f729Sjoerg return nullptr;
29967330f729Sjoerg Diag(ExistingAttr->getLocation(), diag::warn_mismatched_section)
29977330f729Sjoerg << 1 /*section*/;
29987330f729Sjoerg Diag(CI.getLoc(), diag::note_previous_attribute);
29997330f729Sjoerg return nullptr;
30007330f729Sjoerg }
30017330f729Sjoerg return ::new (Context) SectionAttr(Context, CI, Name);
30027330f729Sjoerg }
30037330f729Sjoerg
3004*e038c9c4Sjoerg /// Used to implement to perform semantic checking on
3005*e038c9c4Sjoerg /// attribute((section("foo"))) specifiers.
3006*e038c9c4Sjoerg ///
3007*e038c9c4Sjoerg /// In this case, "foo" is passed in to be checked. If the section
3008*e038c9c4Sjoerg /// specifier is invalid, return an Error that indicates the problem.
3009*e038c9c4Sjoerg ///
3010*e038c9c4Sjoerg /// This is a simple quality of implementation feature to catch errors
3011*e038c9c4Sjoerg /// and give good diagnostics in cases when the assembler or code generator
3012*e038c9c4Sjoerg /// would otherwise reject the section specifier.
isValidSectionSpecifier(StringRef SecName)3013*e038c9c4Sjoerg llvm::Error Sema::isValidSectionSpecifier(StringRef SecName) {
3014*e038c9c4Sjoerg if (!Context.getTargetInfo().getTriple().isOSDarwin())
3015*e038c9c4Sjoerg return llvm::Error::success();
3016*e038c9c4Sjoerg
3017*e038c9c4Sjoerg // Let MCSectionMachO validate this.
3018*e038c9c4Sjoerg StringRef Segment, Section;
3019*e038c9c4Sjoerg unsigned TAA, StubSize;
3020*e038c9c4Sjoerg bool HasTAA;
3021*e038c9c4Sjoerg return llvm::MCSectionMachO::ParseSectionSpecifier(SecName, Segment, Section,
3022*e038c9c4Sjoerg TAA, HasTAA, StubSize);
3023*e038c9c4Sjoerg }
3024*e038c9c4Sjoerg
checkSectionName(SourceLocation LiteralLoc,StringRef SecName)30257330f729Sjoerg bool Sema::checkSectionName(SourceLocation LiteralLoc, StringRef SecName) {
3026*e038c9c4Sjoerg if (llvm::Error E = isValidSectionSpecifier(SecName)) {
3027*e038c9c4Sjoerg Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target)
3028*e038c9c4Sjoerg << toString(std::move(E)) << 1 /*'section'*/;
30297330f729Sjoerg return false;
30307330f729Sjoerg }
30317330f729Sjoerg return true;
30327330f729Sjoerg }
30337330f729Sjoerg
handleSectionAttr(Sema & S,Decl * D,const ParsedAttr & AL)30347330f729Sjoerg static void handleSectionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
30357330f729Sjoerg // Make sure that there is a string literal as the sections's single
30367330f729Sjoerg // argument.
30377330f729Sjoerg StringRef Str;
30387330f729Sjoerg SourceLocation LiteralLoc;
30397330f729Sjoerg if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc))
30407330f729Sjoerg return;
30417330f729Sjoerg
30427330f729Sjoerg if (!S.checkSectionName(LiteralLoc, Str))
30437330f729Sjoerg return;
30447330f729Sjoerg
30457330f729Sjoerg SectionAttr *NewAttr = S.mergeSectionAttr(D, AL, Str);
3046*e038c9c4Sjoerg if (NewAttr) {
30477330f729Sjoerg D->addAttr(NewAttr);
3048*e038c9c4Sjoerg if (isa<FunctionDecl, FunctionTemplateDecl, ObjCMethodDecl,
3049*e038c9c4Sjoerg ObjCPropertyDecl>(D))
3050*e038c9c4Sjoerg S.UnifySection(NewAttr->getName(),
3051*e038c9c4Sjoerg ASTContext::PSF_Execute | ASTContext::PSF_Read,
3052*e038c9c4Sjoerg cast<NamedDecl>(D));
3053*e038c9c4Sjoerg }
30547330f729Sjoerg }
30557330f729Sjoerg
30567330f729Sjoerg // This is used for `__declspec(code_seg("segname"))` on a decl.
30577330f729Sjoerg // `#pragma code_seg("segname")` uses checkSectionName() instead.
checkCodeSegName(Sema & S,SourceLocation LiteralLoc,StringRef CodeSegName)30587330f729Sjoerg static bool checkCodeSegName(Sema &S, SourceLocation LiteralLoc,
30597330f729Sjoerg StringRef CodeSegName) {
3060*e038c9c4Sjoerg if (llvm::Error E = S.isValidSectionSpecifier(CodeSegName)) {
30617330f729Sjoerg S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target)
3062*e038c9c4Sjoerg << toString(std::move(E)) << 0 /*'code-seg'*/;
30637330f729Sjoerg return false;
30647330f729Sjoerg }
30657330f729Sjoerg
30667330f729Sjoerg return true;
30677330f729Sjoerg }
30687330f729Sjoerg
mergeCodeSegAttr(Decl * D,const AttributeCommonInfo & CI,StringRef Name)30697330f729Sjoerg CodeSegAttr *Sema::mergeCodeSegAttr(Decl *D, const AttributeCommonInfo &CI,
30707330f729Sjoerg StringRef Name) {
30717330f729Sjoerg // Explicit or partial specializations do not inherit
30727330f729Sjoerg // the code_seg attribute from the primary template.
30737330f729Sjoerg if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
30747330f729Sjoerg if (FD->isFunctionTemplateSpecialization())
30757330f729Sjoerg return nullptr;
30767330f729Sjoerg }
30777330f729Sjoerg if (const auto *ExistingAttr = D->getAttr<CodeSegAttr>()) {
30787330f729Sjoerg if (ExistingAttr->getName() == Name)
30797330f729Sjoerg return nullptr;
30807330f729Sjoerg Diag(ExistingAttr->getLocation(), diag::warn_mismatched_section)
30817330f729Sjoerg << 0 /*codeseg*/;
30827330f729Sjoerg Diag(CI.getLoc(), diag::note_previous_attribute);
30837330f729Sjoerg return nullptr;
30847330f729Sjoerg }
30857330f729Sjoerg return ::new (Context) CodeSegAttr(Context, CI, Name);
30867330f729Sjoerg }
30877330f729Sjoerg
handleCodeSegAttr(Sema & S,Decl * D,const ParsedAttr & AL)30887330f729Sjoerg static void handleCodeSegAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
30897330f729Sjoerg StringRef Str;
30907330f729Sjoerg SourceLocation LiteralLoc;
30917330f729Sjoerg if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc))
30927330f729Sjoerg return;
30937330f729Sjoerg if (!checkCodeSegName(S, LiteralLoc, Str))
30947330f729Sjoerg return;
30957330f729Sjoerg if (const auto *ExistingAttr = D->getAttr<CodeSegAttr>()) {
30967330f729Sjoerg if (!ExistingAttr->isImplicit()) {
30977330f729Sjoerg S.Diag(AL.getLoc(),
30987330f729Sjoerg ExistingAttr->getName() == Str
30997330f729Sjoerg ? diag::warn_duplicate_codeseg_attribute
31007330f729Sjoerg : diag::err_conflicting_codeseg_attribute);
31017330f729Sjoerg return;
31027330f729Sjoerg }
31037330f729Sjoerg D->dropAttr<CodeSegAttr>();
31047330f729Sjoerg }
31057330f729Sjoerg if (CodeSegAttr *CSA = S.mergeCodeSegAttr(D, AL, Str))
31067330f729Sjoerg D->addAttr(CSA);
31077330f729Sjoerg }
31087330f729Sjoerg
31097330f729Sjoerg // Check for things we'd like to warn about. Multiversioning issues are
31107330f729Sjoerg // handled later in the process, once we know how many exist.
checkTargetAttr(SourceLocation LiteralLoc,StringRef AttrStr)31117330f729Sjoerg bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) {
3112*e038c9c4Sjoerg enum FirstParam { Unsupported, Duplicate, Unknown };
3113*e038c9c4Sjoerg enum SecondParam { None, Architecture, Tune };
3114*e038c9c4Sjoerg if (AttrStr.find("fpmath=") != StringRef::npos)
31157330f729Sjoerg return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
3116*e038c9c4Sjoerg << Unsupported << None << "fpmath=";
31177330f729Sjoerg
3118*e038c9c4Sjoerg // Diagnose use of tune if target doesn't support it.
3119*e038c9c4Sjoerg if (!Context.getTargetInfo().supportsTargetAttributeTune() &&
3120*e038c9c4Sjoerg AttrStr.find("tune=") != StringRef::npos)
3121*e038c9c4Sjoerg return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
3122*e038c9c4Sjoerg << Unsupported << None << "tune=";
3123*e038c9c4Sjoerg
3124*e038c9c4Sjoerg ParsedTargetAttr ParsedAttrs = TargetAttr::parse(AttrStr);
31257330f729Sjoerg
31267330f729Sjoerg if (!ParsedAttrs.Architecture.empty() &&
31277330f729Sjoerg !Context.getTargetInfo().isValidCPUName(ParsedAttrs.Architecture))
31287330f729Sjoerg return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
3129*e038c9c4Sjoerg << Unknown << Architecture << ParsedAttrs.Architecture;
3130*e038c9c4Sjoerg
3131*e038c9c4Sjoerg if (!ParsedAttrs.Tune.empty() &&
3132*e038c9c4Sjoerg !Context.getTargetInfo().isValidCPUName(ParsedAttrs.Tune))
3133*e038c9c4Sjoerg return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
3134*e038c9c4Sjoerg << Unknown << Tune << ParsedAttrs.Tune;
31357330f729Sjoerg
31367330f729Sjoerg if (ParsedAttrs.DuplicateArchitecture)
31377330f729Sjoerg return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
31387330f729Sjoerg << Duplicate << None << "arch=";
3139*e038c9c4Sjoerg if (ParsedAttrs.DuplicateTune)
3140*e038c9c4Sjoerg return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
3141*e038c9c4Sjoerg << Duplicate << None << "tune=";
31427330f729Sjoerg
31437330f729Sjoerg for (const auto &Feature : ParsedAttrs.Features) {
31447330f729Sjoerg auto CurFeature = StringRef(Feature).drop_front(); // remove + or -.
31457330f729Sjoerg if (!Context.getTargetInfo().isValidFeatureName(CurFeature))
31467330f729Sjoerg return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
31477330f729Sjoerg << Unsupported << None << CurFeature;
31487330f729Sjoerg }
31497330f729Sjoerg
3150*e038c9c4Sjoerg TargetInfo::BranchProtectionInfo BPI;
3151*e038c9c4Sjoerg StringRef Error;
3152*e038c9c4Sjoerg if (!ParsedAttrs.BranchProtection.empty() &&
3153*e038c9c4Sjoerg !Context.getTargetInfo().validateBranchProtection(
3154*e038c9c4Sjoerg ParsedAttrs.BranchProtection, BPI, Error)) {
3155*e038c9c4Sjoerg if (Error.empty())
3156*e038c9c4Sjoerg return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
3157*e038c9c4Sjoerg << Unsupported << None << "branch-protection";
3158*e038c9c4Sjoerg else
3159*e038c9c4Sjoerg return Diag(LiteralLoc, diag::err_invalid_branch_protection_spec)
3160*e038c9c4Sjoerg << Error;
3161*e038c9c4Sjoerg }
3162*e038c9c4Sjoerg
31637330f729Sjoerg return false;
31647330f729Sjoerg }
31657330f729Sjoerg
handleTargetAttr(Sema & S,Decl * D,const ParsedAttr & AL)31667330f729Sjoerg static void handleTargetAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
31677330f729Sjoerg StringRef Str;
31687330f729Sjoerg SourceLocation LiteralLoc;
31697330f729Sjoerg if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc) ||
31707330f729Sjoerg S.checkTargetAttr(LiteralLoc, Str))
31717330f729Sjoerg return;
31727330f729Sjoerg
31737330f729Sjoerg TargetAttr *NewAttr = ::new (S.Context) TargetAttr(S.Context, AL, Str);
31747330f729Sjoerg D->addAttr(NewAttr);
31757330f729Sjoerg }
31767330f729Sjoerg
handleMinVectorWidthAttr(Sema & S,Decl * D,const ParsedAttr & AL)31777330f729Sjoerg static void handleMinVectorWidthAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
31787330f729Sjoerg Expr *E = AL.getArgAsExpr(0);
31797330f729Sjoerg uint32_t VecWidth;
31807330f729Sjoerg if (!checkUInt32Argument(S, AL, E, VecWidth)) {
31817330f729Sjoerg AL.setInvalid();
31827330f729Sjoerg return;
31837330f729Sjoerg }
31847330f729Sjoerg
31857330f729Sjoerg MinVectorWidthAttr *Existing = D->getAttr<MinVectorWidthAttr>();
31867330f729Sjoerg if (Existing && Existing->getVectorWidth() != VecWidth) {
31877330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
31887330f729Sjoerg return;
31897330f729Sjoerg }
31907330f729Sjoerg
31917330f729Sjoerg D->addAttr(::new (S.Context) MinVectorWidthAttr(S.Context, AL, VecWidth));
31927330f729Sjoerg }
31937330f729Sjoerg
handleCleanupAttr(Sema & S,Decl * D,const ParsedAttr & AL)31947330f729Sjoerg static void handleCleanupAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
31957330f729Sjoerg Expr *E = AL.getArgAsExpr(0);
31967330f729Sjoerg SourceLocation Loc = E->getExprLoc();
31977330f729Sjoerg FunctionDecl *FD = nullptr;
31987330f729Sjoerg DeclarationNameInfo NI;
31997330f729Sjoerg
32007330f729Sjoerg // gcc only allows for simple identifiers. Since we support more than gcc, we
32017330f729Sjoerg // will warn the user.
32027330f729Sjoerg if (auto *DRE = dyn_cast<DeclRefExpr>(E)) {
32037330f729Sjoerg if (DRE->hasQualifier())
32047330f729Sjoerg S.Diag(Loc, diag::warn_cleanup_ext);
32057330f729Sjoerg FD = dyn_cast<FunctionDecl>(DRE->getDecl());
32067330f729Sjoerg NI = DRE->getNameInfo();
32077330f729Sjoerg if (!FD) {
32087330f729Sjoerg S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 1
32097330f729Sjoerg << NI.getName();
32107330f729Sjoerg return;
32117330f729Sjoerg }
32127330f729Sjoerg } else if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
32137330f729Sjoerg if (ULE->hasExplicitTemplateArgs())
32147330f729Sjoerg S.Diag(Loc, diag::warn_cleanup_ext);
32157330f729Sjoerg FD = S.ResolveSingleFunctionTemplateSpecialization(ULE, true);
32167330f729Sjoerg NI = ULE->getNameInfo();
32177330f729Sjoerg if (!FD) {
32187330f729Sjoerg S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 2
32197330f729Sjoerg << NI.getName();
32207330f729Sjoerg if (ULE->getType() == S.Context.OverloadTy)
32217330f729Sjoerg S.NoteAllOverloadCandidates(ULE);
32227330f729Sjoerg return;
32237330f729Sjoerg }
32247330f729Sjoerg } else {
32257330f729Sjoerg S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 0;
32267330f729Sjoerg return;
32277330f729Sjoerg }
32287330f729Sjoerg
32297330f729Sjoerg if (FD->getNumParams() != 1) {
32307330f729Sjoerg S.Diag(Loc, diag::err_attribute_cleanup_func_must_take_one_arg)
32317330f729Sjoerg << NI.getName();
32327330f729Sjoerg return;
32337330f729Sjoerg }
32347330f729Sjoerg
32357330f729Sjoerg // We're currently more strict than GCC about what function types we accept.
32367330f729Sjoerg // If this ever proves to be a problem it should be easy to fix.
32377330f729Sjoerg QualType Ty = S.Context.getPointerType(cast<VarDecl>(D)->getType());
32387330f729Sjoerg QualType ParamTy = FD->getParamDecl(0)->getType();
32397330f729Sjoerg if (S.CheckAssignmentConstraints(FD->getParamDecl(0)->getLocation(),
32407330f729Sjoerg ParamTy, Ty) != Sema::Compatible) {
32417330f729Sjoerg S.Diag(Loc, diag::err_attribute_cleanup_func_arg_incompatible_type)
32427330f729Sjoerg << NI.getName() << ParamTy << Ty;
32437330f729Sjoerg return;
32447330f729Sjoerg }
32457330f729Sjoerg
32467330f729Sjoerg D->addAttr(::new (S.Context) CleanupAttr(S.Context, AL, FD));
32477330f729Sjoerg }
32487330f729Sjoerg
handleEnumExtensibilityAttr(Sema & S,Decl * D,const ParsedAttr & AL)32497330f729Sjoerg static void handleEnumExtensibilityAttr(Sema &S, Decl *D,
32507330f729Sjoerg const ParsedAttr &AL) {
32517330f729Sjoerg if (!AL.isArgIdent(0)) {
32527330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
32537330f729Sjoerg << AL << 0 << AANT_ArgumentIdentifier;
32547330f729Sjoerg return;
32557330f729Sjoerg }
32567330f729Sjoerg
32577330f729Sjoerg EnumExtensibilityAttr::Kind ExtensibilityKind;
32587330f729Sjoerg IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
32597330f729Sjoerg if (!EnumExtensibilityAttr::ConvertStrToKind(II->getName(),
32607330f729Sjoerg ExtensibilityKind)) {
32617330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II;
32627330f729Sjoerg return;
32637330f729Sjoerg }
32647330f729Sjoerg
32657330f729Sjoerg D->addAttr(::new (S.Context)
32667330f729Sjoerg EnumExtensibilityAttr(S.Context, AL, ExtensibilityKind));
32677330f729Sjoerg }
32687330f729Sjoerg
32697330f729Sjoerg /// Handle __attribute__((format_arg((idx)))) attribute based on
32707330f729Sjoerg /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
handleFormatArgAttr(Sema & S,Decl * D,const ParsedAttr & AL)32717330f729Sjoerg static void handleFormatArgAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
32727330f729Sjoerg Expr *IdxExpr = AL.getArgAsExpr(0);
32737330f729Sjoerg ParamIdx Idx;
32747330f729Sjoerg if (!checkFunctionOrMethodParameterIndex(S, D, AL, 1, IdxExpr, Idx))
32757330f729Sjoerg return;
32767330f729Sjoerg
32777330f729Sjoerg // Make sure the format string is really a string.
32787330f729Sjoerg QualType Ty = getFunctionOrMethodParamType(D, Idx.getASTIndex());
32797330f729Sjoerg
32807330f729Sjoerg bool NotNSStringTy = !isNSStringType(Ty, S.Context);
32817330f729Sjoerg if (NotNSStringTy &&
32827330f729Sjoerg !isCFStringType(Ty, S.Context) &&
32837330f729Sjoerg (!Ty->isPointerType() ||
32847330f729Sjoerg !Ty->castAs<PointerType>()->getPointeeType()->isCharType())) {
32857330f729Sjoerg S.Diag(AL.getLoc(), diag::err_format_attribute_not)
32867330f729Sjoerg << "a string type" << IdxExpr->getSourceRange()
32877330f729Sjoerg << getFunctionOrMethodParamRange(D, 0);
32887330f729Sjoerg return;
32897330f729Sjoerg }
32907330f729Sjoerg Ty = getFunctionOrMethodResultType(D);
3291*e038c9c4Sjoerg if (!isNSStringType(Ty, S.Context, /*AllowNSAttributedString=*/true) &&
32927330f729Sjoerg !isCFStringType(Ty, S.Context) &&
32937330f729Sjoerg (!Ty->isPointerType() ||
32947330f729Sjoerg !Ty->castAs<PointerType>()->getPointeeType()->isCharType())) {
32957330f729Sjoerg S.Diag(AL.getLoc(), diag::err_format_attribute_result_not)
32967330f729Sjoerg << (NotNSStringTy ? "string type" : "NSString")
32977330f729Sjoerg << IdxExpr->getSourceRange() << getFunctionOrMethodParamRange(D, 0);
32987330f729Sjoerg return;
32997330f729Sjoerg }
33007330f729Sjoerg
33017330f729Sjoerg D->addAttr(::new (S.Context) FormatArgAttr(S.Context, AL, Idx));
33027330f729Sjoerg }
33037330f729Sjoerg
33047330f729Sjoerg enum FormatAttrKind {
33057330f729Sjoerg CFStringFormat,
33067330f729Sjoerg NSStringFormat,
33077330f729Sjoerg StrftimeFormat,
33087330f729Sjoerg SupportedFormat,
33097330f729Sjoerg IgnoredFormat,
33107330f729Sjoerg InvalidFormat
33117330f729Sjoerg };
33127330f729Sjoerg
33137330f729Sjoerg /// getFormatAttrKind - Map from format attribute names to supported format
33147330f729Sjoerg /// types.
getFormatAttrKind(StringRef Format)33157330f729Sjoerg static FormatAttrKind getFormatAttrKind(StringRef Format) {
33167330f729Sjoerg return llvm::StringSwitch<FormatAttrKind>(Format)
33177330f729Sjoerg // Check for formats that get handled specially.
33187330f729Sjoerg .Case("NSString", NSStringFormat)
33197330f729Sjoerg .Case("CFString", CFStringFormat)
33207330f729Sjoerg .Case("strftime", StrftimeFormat)
33217330f729Sjoerg
33227330f729Sjoerg // Otherwise, check for supported formats.
33237330f729Sjoerg .Cases("scanf", "printf", "printf0", "strfmon", SupportedFormat)
33247330f729Sjoerg .Cases("cmn_err", "vcmn_err", "zcmn_err", SupportedFormat)
33257330f729Sjoerg .Case("kprintf", SupportedFormat) // OpenBSD.
33267330f729Sjoerg .Case("freebsd_kprintf", SupportedFormat) // FreeBSD.
33277330f729Sjoerg .Case("os_trace", SupportedFormat)
33287330f729Sjoerg .Case("os_log", SupportedFormat)
33297330f729Sjoerg
33307330f729Sjoerg .Cases("gcc_diag", "gcc_cdiag", "gcc_cxxdiag", "gcc_tdiag", IgnoredFormat)
33317330f729Sjoerg .Default(InvalidFormat);
33327330f729Sjoerg }
33337330f729Sjoerg
33347330f729Sjoerg /// Handle __attribute__((init_priority(priority))) attributes based on
33357330f729Sjoerg /// http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html
handleInitPriorityAttr(Sema & S,Decl * D,const ParsedAttr & AL)33367330f729Sjoerg static void handleInitPriorityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
33377330f729Sjoerg if (!S.getLangOpts().CPlusPlus) {
33387330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL;
33397330f729Sjoerg return;
33407330f729Sjoerg }
33417330f729Sjoerg
33427330f729Sjoerg if (S.getCurFunctionOrMethodDecl()) {
33437330f729Sjoerg S.Diag(AL.getLoc(), diag::err_init_priority_object_attr);
33447330f729Sjoerg AL.setInvalid();
33457330f729Sjoerg return;
33467330f729Sjoerg }
33477330f729Sjoerg QualType T = cast<VarDecl>(D)->getType();
33487330f729Sjoerg if (S.Context.getAsArrayType(T))
33497330f729Sjoerg T = S.Context.getBaseElementType(T);
33507330f729Sjoerg if (!T->getAs<RecordType>()) {
33517330f729Sjoerg S.Diag(AL.getLoc(), diag::err_init_priority_object_attr);
33527330f729Sjoerg AL.setInvalid();
33537330f729Sjoerg return;
33547330f729Sjoerg }
33557330f729Sjoerg
33567330f729Sjoerg Expr *E = AL.getArgAsExpr(0);
33577330f729Sjoerg uint32_t prioritynum;
33587330f729Sjoerg if (!checkUInt32Argument(S, AL, E, prioritynum)) {
33597330f729Sjoerg AL.setInvalid();
33607330f729Sjoerg return;
33617330f729Sjoerg }
33627330f729Sjoerg
3363*e038c9c4Sjoerg // Only perform the priority check if the attribute is outside of a system
3364*e038c9c4Sjoerg // header. Values <= 100 are reserved for the implementation, and libc++
3365*e038c9c4Sjoerg // benefits from being able to specify values in that range.
3366*e038c9c4Sjoerg if ((prioritynum < 101 || prioritynum > 65535) &&
3367*e038c9c4Sjoerg !S.getSourceManager().isInSystemHeader(AL.getLoc())) {
33687330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_range)
33697330f729Sjoerg << E->getSourceRange() << AL << 101 << 65535;
33707330f729Sjoerg AL.setInvalid();
33717330f729Sjoerg return;
33727330f729Sjoerg }
33737330f729Sjoerg D->addAttr(::new (S.Context) InitPriorityAttr(S.Context, AL, prioritynum));
33747330f729Sjoerg }
33757330f729Sjoerg
mergeFormatAttr(Decl * D,const AttributeCommonInfo & CI,IdentifierInfo * Format,int FormatIdx,int FirstArg)33767330f729Sjoerg FormatAttr *Sema::mergeFormatAttr(Decl *D, const AttributeCommonInfo &CI,
33777330f729Sjoerg IdentifierInfo *Format, int FormatIdx,
33787330f729Sjoerg int FirstArg) {
33797330f729Sjoerg // Check whether we already have an equivalent format attribute.
33807330f729Sjoerg for (auto *F : D->specific_attrs<FormatAttr>()) {
33817330f729Sjoerg if (F->getType() == Format &&
33827330f729Sjoerg F->getFormatIdx() == FormatIdx &&
33837330f729Sjoerg F->getFirstArg() == FirstArg) {
33847330f729Sjoerg // If we don't have a valid location for this attribute, adopt the
33857330f729Sjoerg // location.
33867330f729Sjoerg if (F->getLocation().isInvalid())
33877330f729Sjoerg F->setRange(CI.getRange());
33887330f729Sjoerg return nullptr;
33897330f729Sjoerg }
33907330f729Sjoerg }
33917330f729Sjoerg
33927330f729Sjoerg return ::new (Context) FormatAttr(Context, CI, Format, FormatIdx, FirstArg);
33937330f729Sjoerg }
33947330f729Sjoerg
33957330f729Sjoerg /// Handle __attribute__((format(type,idx,firstarg))) attributes based on
33967330f729Sjoerg /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
handleFormatAttr(Sema & S,Decl * D,const ParsedAttr & AL)33977330f729Sjoerg static void handleFormatAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
33987330f729Sjoerg if (!AL.isArgIdent(0)) {
33997330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
34007330f729Sjoerg << AL << 1 << AANT_ArgumentIdentifier;
34017330f729Sjoerg return;
34027330f729Sjoerg }
34037330f729Sjoerg
34047330f729Sjoerg // In C++ the implicit 'this' function parameter also counts, and they are
34057330f729Sjoerg // counted from one.
34067330f729Sjoerg bool HasImplicitThisParam = isInstanceMethod(D);
34077330f729Sjoerg unsigned NumArgs = getFunctionOrMethodNumParams(D) + HasImplicitThisParam;
34087330f729Sjoerg
34097330f729Sjoerg IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
34107330f729Sjoerg StringRef Format = II->getName();
34117330f729Sjoerg
34127330f729Sjoerg if (normalizeName(Format)) {
34137330f729Sjoerg // If we've modified the string name, we need a new identifier for it.
34147330f729Sjoerg II = &S.Context.Idents.get(Format);
34157330f729Sjoerg }
34167330f729Sjoerg
34177330f729Sjoerg // Check for supported formats.
34187330f729Sjoerg FormatAttrKind Kind = getFormatAttrKind(Format);
34197330f729Sjoerg
34207330f729Sjoerg if (Kind == IgnoredFormat)
34217330f729Sjoerg return;
34227330f729Sjoerg
34237330f729Sjoerg if (Kind == InvalidFormat) {
34247330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
34257330f729Sjoerg << AL << II->getName();
34267330f729Sjoerg return;
34277330f729Sjoerg }
34287330f729Sjoerg
34297330f729Sjoerg // checks for the 2nd argument
34307330f729Sjoerg Expr *IdxExpr = AL.getArgAsExpr(1);
34317330f729Sjoerg uint32_t Idx;
34327330f729Sjoerg if (!checkUInt32Argument(S, AL, IdxExpr, Idx, 2))
34337330f729Sjoerg return;
34347330f729Sjoerg
34357330f729Sjoerg if (Idx < 1 || Idx > NumArgs) {
34367330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
34377330f729Sjoerg << AL << 2 << IdxExpr->getSourceRange();
34387330f729Sjoerg return;
34397330f729Sjoerg }
34407330f729Sjoerg
34417330f729Sjoerg // FIXME: Do we need to bounds check?
34427330f729Sjoerg unsigned ArgIdx = Idx - 1;
34437330f729Sjoerg
34447330f729Sjoerg if (HasImplicitThisParam) {
34457330f729Sjoerg if (ArgIdx == 0) {
34467330f729Sjoerg S.Diag(AL.getLoc(),
34477330f729Sjoerg diag::err_format_attribute_implicit_this_format_string)
34487330f729Sjoerg << IdxExpr->getSourceRange();
34497330f729Sjoerg return;
34507330f729Sjoerg }
34517330f729Sjoerg ArgIdx--;
34527330f729Sjoerg }
34537330f729Sjoerg
34547330f729Sjoerg // make sure the format string is really a string
34557330f729Sjoerg QualType Ty = getFunctionOrMethodParamType(D, ArgIdx);
34567330f729Sjoerg
34577330f729Sjoerg if (Kind == CFStringFormat) {
34587330f729Sjoerg if (!isCFStringType(Ty, S.Context)) {
34597330f729Sjoerg S.Diag(AL.getLoc(), diag::err_format_attribute_not)
34607330f729Sjoerg << "a CFString" << IdxExpr->getSourceRange()
34617330f729Sjoerg << getFunctionOrMethodParamRange(D, ArgIdx);
34627330f729Sjoerg return;
34637330f729Sjoerg }
34647330f729Sjoerg } else if (Kind == NSStringFormat) {
34657330f729Sjoerg // FIXME: do we need to check if the type is NSString*? What are the
34667330f729Sjoerg // semantics?
34677330f729Sjoerg if (!isNSStringType(Ty, S.Context)) {
34687330f729Sjoerg S.Diag(AL.getLoc(), diag::err_format_attribute_not)
34697330f729Sjoerg << "an NSString" << IdxExpr->getSourceRange()
34707330f729Sjoerg << getFunctionOrMethodParamRange(D, ArgIdx);
34717330f729Sjoerg return;
34727330f729Sjoerg }
34737330f729Sjoerg } else if (!Ty->isPointerType() ||
34747330f729Sjoerg !Ty->castAs<PointerType>()->getPointeeType()->isCharType()) {
34757330f729Sjoerg S.Diag(AL.getLoc(), diag::err_format_attribute_not)
34767330f729Sjoerg << "a string type" << IdxExpr->getSourceRange()
34777330f729Sjoerg << getFunctionOrMethodParamRange(D, ArgIdx);
34787330f729Sjoerg return;
34797330f729Sjoerg }
34807330f729Sjoerg
34817330f729Sjoerg // check the 3rd argument
34827330f729Sjoerg Expr *FirstArgExpr = AL.getArgAsExpr(2);
34837330f729Sjoerg uint32_t FirstArg;
34847330f729Sjoerg if (!checkUInt32Argument(S, AL, FirstArgExpr, FirstArg, 3))
34857330f729Sjoerg return;
34867330f729Sjoerg
34877330f729Sjoerg // check if the function is variadic if the 3rd argument non-zero
34887330f729Sjoerg if (FirstArg != 0) {
34897330f729Sjoerg if (isFunctionOrMethodVariadic(D)) {
34907330f729Sjoerg ++NumArgs; // +1 for ...
34917330f729Sjoerg } else {
34927330f729Sjoerg S.Diag(D->getLocation(), diag::err_format_attribute_requires_variadic);
34937330f729Sjoerg return;
34947330f729Sjoerg }
34957330f729Sjoerg }
34967330f729Sjoerg
34977330f729Sjoerg // strftime requires FirstArg to be 0 because it doesn't read from any
34987330f729Sjoerg // variable the input is just the current time + the format string.
34997330f729Sjoerg if (Kind == StrftimeFormat) {
35007330f729Sjoerg if (FirstArg != 0) {
35017330f729Sjoerg S.Diag(AL.getLoc(), diag::err_format_strftime_third_parameter)
35027330f729Sjoerg << FirstArgExpr->getSourceRange();
35037330f729Sjoerg return;
35047330f729Sjoerg }
35057330f729Sjoerg // if 0 it disables parameter checking (to use with e.g. va_list)
35067330f729Sjoerg } else if (FirstArg != 0 && FirstArg != NumArgs) {
35077330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
35087330f729Sjoerg << AL << 3 << FirstArgExpr->getSourceRange();
35097330f729Sjoerg return;
35107330f729Sjoerg }
35117330f729Sjoerg
35127330f729Sjoerg FormatAttr *NewAttr = S.mergeFormatAttr(D, AL, II, Idx, FirstArg);
35137330f729Sjoerg if (NewAttr)
35147330f729Sjoerg D->addAttr(NewAttr);
35157330f729Sjoerg }
35167330f729Sjoerg
35177330f729Sjoerg /// Handle __attribute__((callback(CalleeIdx, PayloadIdx0, ...))) attributes.
handleCallbackAttr(Sema & S,Decl * D,const ParsedAttr & AL)35187330f729Sjoerg static void handleCallbackAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
35197330f729Sjoerg // The index that identifies the callback callee is mandatory.
35207330f729Sjoerg if (AL.getNumArgs() == 0) {
35217330f729Sjoerg S.Diag(AL.getLoc(), diag::err_callback_attribute_no_callee)
35227330f729Sjoerg << AL.getRange();
35237330f729Sjoerg return;
35247330f729Sjoerg }
35257330f729Sjoerg
35267330f729Sjoerg bool HasImplicitThisParam = isInstanceMethod(D);
35277330f729Sjoerg int32_t NumArgs = getFunctionOrMethodNumParams(D);
35287330f729Sjoerg
35297330f729Sjoerg FunctionDecl *FD = D->getAsFunction();
35307330f729Sjoerg assert(FD && "Expected a function declaration!");
35317330f729Sjoerg
35327330f729Sjoerg llvm::StringMap<int> NameIdxMapping;
35337330f729Sjoerg NameIdxMapping["__"] = -1;
35347330f729Sjoerg
35357330f729Sjoerg NameIdxMapping["this"] = 0;
35367330f729Sjoerg
35377330f729Sjoerg int Idx = 1;
35387330f729Sjoerg for (const ParmVarDecl *PVD : FD->parameters())
35397330f729Sjoerg NameIdxMapping[PVD->getName()] = Idx++;
35407330f729Sjoerg
35417330f729Sjoerg auto UnknownName = NameIdxMapping.end();
35427330f729Sjoerg
35437330f729Sjoerg SmallVector<int, 8> EncodingIndices;
35447330f729Sjoerg for (unsigned I = 0, E = AL.getNumArgs(); I < E; ++I) {
35457330f729Sjoerg SourceRange SR;
35467330f729Sjoerg int32_t ArgIdx;
35477330f729Sjoerg
35487330f729Sjoerg if (AL.isArgIdent(I)) {
35497330f729Sjoerg IdentifierLoc *IdLoc = AL.getArgAsIdent(I);
35507330f729Sjoerg auto It = NameIdxMapping.find(IdLoc->Ident->getName());
35517330f729Sjoerg if (It == UnknownName) {
35527330f729Sjoerg S.Diag(AL.getLoc(), diag::err_callback_attribute_argument_unknown)
35537330f729Sjoerg << IdLoc->Ident << IdLoc->Loc;
35547330f729Sjoerg return;
35557330f729Sjoerg }
35567330f729Sjoerg
35577330f729Sjoerg SR = SourceRange(IdLoc->Loc);
35587330f729Sjoerg ArgIdx = It->second;
35597330f729Sjoerg } else if (AL.isArgExpr(I)) {
35607330f729Sjoerg Expr *IdxExpr = AL.getArgAsExpr(I);
35617330f729Sjoerg
35627330f729Sjoerg // If the expression is not parseable as an int32_t we have a problem.
35637330f729Sjoerg if (!checkUInt32Argument(S, AL, IdxExpr, (uint32_t &)ArgIdx, I + 1,
35647330f729Sjoerg false)) {
35657330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
35667330f729Sjoerg << AL << (I + 1) << IdxExpr->getSourceRange();
35677330f729Sjoerg return;
35687330f729Sjoerg }
35697330f729Sjoerg
35707330f729Sjoerg // Check oob, excluding the special values, 0 and -1.
35717330f729Sjoerg if (ArgIdx < -1 || ArgIdx > NumArgs) {
35727330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
35737330f729Sjoerg << AL << (I + 1) << IdxExpr->getSourceRange();
35747330f729Sjoerg return;
35757330f729Sjoerg }
35767330f729Sjoerg
35777330f729Sjoerg SR = IdxExpr->getSourceRange();
35787330f729Sjoerg } else {
35797330f729Sjoerg llvm_unreachable("Unexpected ParsedAttr argument type!");
35807330f729Sjoerg }
35817330f729Sjoerg
35827330f729Sjoerg if (ArgIdx == 0 && !HasImplicitThisParam) {
35837330f729Sjoerg S.Diag(AL.getLoc(), diag::err_callback_implicit_this_not_available)
35847330f729Sjoerg << (I + 1) << SR;
35857330f729Sjoerg return;
35867330f729Sjoerg }
35877330f729Sjoerg
35887330f729Sjoerg // Adjust for the case we do not have an implicit "this" parameter. In this
35897330f729Sjoerg // case we decrease all positive values by 1 to get LLVM argument indices.
35907330f729Sjoerg if (!HasImplicitThisParam && ArgIdx > 0)
35917330f729Sjoerg ArgIdx -= 1;
35927330f729Sjoerg
35937330f729Sjoerg EncodingIndices.push_back(ArgIdx);
35947330f729Sjoerg }
35957330f729Sjoerg
35967330f729Sjoerg int CalleeIdx = EncodingIndices.front();
35977330f729Sjoerg // Check if the callee index is proper, thus not "this" and not "unknown".
35987330f729Sjoerg // This means the "CalleeIdx" has to be non-negative if "HasImplicitThisParam"
35997330f729Sjoerg // is false and positive if "HasImplicitThisParam" is true.
36007330f729Sjoerg if (CalleeIdx < (int)HasImplicitThisParam) {
36017330f729Sjoerg S.Diag(AL.getLoc(), diag::err_callback_attribute_invalid_callee)
36027330f729Sjoerg << AL.getRange();
36037330f729Sjoerg return;
36047330f729Sjoerg }
36057330f729Sjoerg
36067330f729Sjoerg // Get the callee type, note the index adjustment as the AST doesn't contain
36077330f729Sjoerg // the this type (which the callee cannot reference anyway!).
36087330f729Sjoerg const Type *CalleeType =
36097330f729Sjoerg getFunctionOrMethodParamType(D, CalleeIdx - HasImplicitThisParam)
36107330f729Sjoerg .getTypePtr();
36117330f729Sjoerg if (!CalleeType || !CalleeType->isFunctionPointerType()) {
36127330f729Sjoerg S.Diag(AL.getLoc(), diag::err_callback_callee_no_function_type)
36137330f729Sjoerg << AL.getRange();
36147330f729Sjoerg return;
36157330f729Sjoerg }
36167330f729Sjoerg
36177330f729Sjoerg const Type *CalleeFnType =
36187330f729Sjoerg CalleeType->getPointeeType()->getUnqualifiedDesugaredType();
36197330f729Sjoerg
36207330f729Sjoerg // TODO: Check the type of the callee arguments.
36217330f729Sjoerg
36227330f729Sjoerg const auto *CalleeFnProtoType = dyn_cast<FunctionProtoType>(CalleeFnType);
36237330f729Sjoerg if (!CalleeFnProtoType) {
36247330f729Sjoerg S.Diag(AL.getLoc(), diag::err_callback_callee_no_function_type)
36257330f729Sjoerg << AL.getRange();
36267330f729Sjoerg return;
36277330f729Sjoerg }
36287330f729Sjoerg
36297330f729Sjoerg if (CalleeFnProtoType->getNumParams() > EncodingIndices.size() - 1) {
36307330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
36317330f729Sjoerg << AL << (unsigned)(EncodingIndices.size() - 1);
36327330f729Sjoerg return;
36337330f729Sjoerg }
36347330f729Sjoerg
36357330f729Sjoerg if (CalleeFnProtoType->getNumParams() < EncodingIndices.size() - 1) {
36367330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
36377330f729Sjoerg << AL << (unsigned)(EncodingIndices.size() - 1);
36387330f729Sjoerg return;
36397330f729Sjoerg }
36407330f729Sjoerg
36417330f729Sjoerg if (CalleeFnProtoType->isVariadic()) {
36427330f729Sjoerg S.Diag(AL.getLoc(), diag::err_callback_callee_is_variadic) << AL.getRange();
36437330f729Sjoerg return;
36447330f729Sjoerg }
36457330f729Sjoerg
36467330f729Sjoerg // Do not allow multiple callback attributes.
36477330f729Sjoerg if (D->hasAttr<CallbackAttr>()) {
36487330f729Sjoerg S.Diag(AL.getLoc(), diag::err_callback_attribute_multiple) << AL.getRange();
36497330f729Sjoerg return;
36507330f729Sjoerg }
36517330f729Sjoerg
36527330f729Sjoerg D->addAttr(::new (S.Context) CallbackAttr(
36537330f729Sjoerg S.Context, AL, EncodingIndices.data(), EncodingIndices.size()));
36547330f729Sjoerg }
36557330f729Sjoerg
isFunctionLike(const Type & T)3656*e038c9c4Sjoerg static bool isFunctionLike(const Type &T) {
3657*e038c9c4Sjoerg // Check for explicit function types.
3658*e038c9c4Sjoerg // 'called_once' is only supported in Objective-C and it has
3659*e038c9c4Sjoerg // function pointers and block pointers.
3660*e038c9c4Sjoerg return T.isFunctionPointerType() || T.isBlockPointerType();
3661*e038c9c4Sjoerg }
3662*e038c9c4Sjoerg
3663*e038c9c4Sjoerg /// Handle 'called_once' attribute.
handleCalledOnceAttr(Sema & S,Decl * D,const ParsedAttr & AL)3664*e038c9c4Sjoerg static void handleCalledOnceAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
3665*e038c9c4Sjoerg // 'called_once' only applies to parameters representing functions.
3666*e038c9c4Sjoerg QualType T = cast<ParmVarDecl>(D)->getType();
3667*e038c9c4Sjoerg
3668*e038c9c4Sjoerg if (!isFunctionLike(*T)) {
3669*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::err_called_once_attribute_wrong_type);
3670*e038c9c4Sjoerg return;
3671*e038c9c4Sjoerg }
3672*e038c9c4Sjoerg
3673*e038c9c4Sjoerg D->addAttr(::new (S.Context) CalledOnceAttr(S.Context, AL));
3674*e038c9c4Sjoerg }
3675*e038c9c4Sjoerg
handleTransparentUnionAttr(Sema & S,Decl * D,const ParsedAttr & AL)36767330f729Sjoerg static void handleTransparentUnionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
36777330f729Sjoerg // Try to find the underlying union declaration.
36787330f729Sjoerg RecordDecl *RD = nullptr;
36797330f729Sjoerg const auto *TD = dyn_cast<TypedefNameDecl>(D);
36807330f729Sjoerg if (TD && TD->getUnderlyingType()->isUnionType())
36817330f729Sjoerg RD = TD->getUnderlyingType()->getAsUnionType()->getDecl();
36827330f729Sjoerg else
36837330f729Sjoerg RD = dyn_cast<RecordDecl>(D);
36847330f729Sjoerg
36857330f729Sjoerg if (!RD || !RD->isUnion()) {
36867330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) << AL
36877330f729Sjoerg << ExpectedUnion;
36887330f729Sjoerg return;
36897330f729Sjoerg }
36907330f729Sjoerg
36917330f729Sjoerg if (!RD->isCompleteDefinition()) {
36927330f729Sjoerg if (!RD->isBeingDefined())
36937330f729Sjoerg S.Diag(AL.getLoc(),
36947330f729Sjoerg diag::warn_transparent_union_attribute_not_definition);
36957330f729Sjoerg return;
36967330f729Sjoerg }
36977330f729Sjoerg
36987330f729Sjoerg RecordDecl::field_iterator Field = RD->field_begin(),
36997330f729Sjoerg FieldEnd = RD->field_end();
37007330f729Sjoerg if (Field == FieldEnd) {
37017330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_transparent_union_attribute_zero_fields);
37027330f729Sjoerg return;
37037330f729Sjoerg }
37047330f729Sjoerg
37057330f729Sjoerg FieldDecl *FirstField = *Field;
37067330f729Sjoerg QualType FirstType = FirstField->getType();
37077330f729Sjoerg if (FirstType->hasFloatingRepresentation() || FirstType->isVectorType()) {
37087330f729Sjoerg S.Diag(FirstField->getLocation(),
37097330f729Sjoerg diag::warn_transparent_union_attribute_floating)
37107330f729Sjoerg << FirstType->isVectorType() << FirstType;
37117330f729Sjoerg return;
37127330f729Sjoerg }
37137330f729Sjoerg
37147330f729Sjoerg if (FirstType->isIncompleteType())
37157330f729Sjoerg return;
37167330f729Sjoerg uint64_t FirstSize = S.Context.getTypeSize(FirstType);
37177330f729Sjoerg uint64_t FirstAlign = S.Context.getTypeAlign(FirstType);
37187330f729Sjoerg for (; Field != FieldEnd; ++Field) {
37197330f729Sjoerg QualType FieldType = Field->getType();
37207330f729Sjoerg if (FieldType->isIncompleteType())
37217330f729Sjoerg return;
37227330f729Sjoerg // FIXME: this isn't fully correct; we also need to test whether the
37237330f729Sjoerg // members of the union would all have the same calling convention as the
37247330f729Sjoerg // first member of the union. Checking just the size and alignment isn't
37257330f729Sjoerg // sufficient (consider structs passed on the stack instead of in registers
37267330f729Sjoerg // as an example).
37277330f729Sjoerg if (S.Context.getTypeSize(FieldType) != FirstSize ||
37287330f729Sjoerg S.Context.getTypeAlign(FieldType) > FirstAlign) {
37297330f729Sjoerg // Warn if we drop the attribute.
37307330f729Sjoerg bool isSize = S.Context.getTypeSize(FieldType) != FirstSize;
37317330f729Sjoerg unsigned FieldBits = isSize ? S.Context.getTypeSize(FieldType)
37327330f729Sjoerg : S.Context.getTypeAlign(FieldType);
37337330f729Sjoerg S.Diag(Field->getLocation(),
37347330f729Sjoerg diag::warn_transparent_union_attribute_field_size_align)
3735*e038c9c4Sjoerg << isSize << *Field << FieldBits;
37367330f729Sjoerg unsigned FirstBits = isSize ? FirstSize : FirstAlign;
37377330f729Sjoerg S.Diag(FirstField->getLocation(),
37387330f729Sjoerg diag::note_transparent_union_first_field_size_align)
37397330f729Sjoerg << isSize << FirstBits;
37407330f729Sjoerg return;
37417330f729Sjoerg }
37427330f729Sjoerg }
37437330f729Sjoerg
37447330f729Sjoerg RD->addAttr(::new (S.Context) TransparentUnionAttr(S.Context, AL));
37457330f729Sjoerg }
37467330f729Sjoerg
AddAnnotationAttr(Decl * D,const AttributeCommonInfo & CI,StringRef Str,MutableArrayRef<Expr * > Args)3747*e038c9c4Sjoerg void Sema::AddAnnotationAttr(Decl *D, const AttributeCommonInfo &CI,
3748*e038c9c4Sjoerg StringRef Str, MutableArrayRef<Expr *> Args) {
3749*e038c9c4Sjoerg auto *Attr = AnnotateAttr::Create(Context, Str, Args.data(), Args.size(), CI);
3750*e038c9c4Sjoerg llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
3751*e038c9c4Sjoerg for (unsigned Idx = 0; Idx < Attr->args_size(); Idx++) {
3752*e038c9c4Sjoerg Expr *&E = Attr->args_begin()[Idx];
3753*e038c9c4Sjoerg assert(E && "error are handled before");
3754*e038c9c4Sjoerg if (E->isValueDependent() || E->isTypeDependent())
3755*e038c9c4Sjoerg continue;
3756*e038c9c4Sjoerg
3757*e038c9c4Sjoerg if (E->getType()->isArrayType())
3758*e038c9c4Sjoerg E = ImpCastExprToType(E, Context.getPointerType(E->getType()),
3759*e038c9c4Sjoerg clang::CK_ArrayToPointerDecay)
3760*e038c9c4Sjoerg .get();
3761*e038c9c4Sjoerg if (E->getType()->isFunctionType())
3762*e038c9c4Sjoerg E = ImplicitCastExpr::Create(Context,
3763*e038c9c4Sjoerg Context.getPointerType(E->getType()),
3764*e038c9c4Sjoerg clang::CK_FunctionToPointerDecay, E, nullptr,
3765*e038c9c4Sjoerg VK_RValue, FPOptionsOverride());
3766*e038c9c4Sjoerg if (E->isLValue())
3767*e038c9c4Sjoerg E = ImplicitCastExpr::Create(Context, E->getType().getNonReferenceType(),
3768*e038c9c4Sjoerg clang::CK_LValueToRValue, E, nullptr,
3769*e038c9c4Sjoerg VK_RValue, FPOptionsOverride());
3770*e038c9c4Sjoerg
3771*e038c9c4Sjoerg Expr::EvalResult Eval;
3772*e038c9c4Sjoerg Notes.clear();
3773*e038c9c4Sjoerg Eval.Diag = &Notes;
3774*e038c9c4Sjoerg
3775*e038c9c4Sjoerg bool Result =
3776*e038c9c4Sjoerg E->EvaluateAsConstantExpr(Eval, Context);
3777*e038c9c4Sjoerg
3778*e038c9c4Sjoerg /// Result means the expression can be folded to a constant.
3779*e038c9c4Sjoerg /// Note.empty() means the expression is a valid constant expression in the
3780*e038c9c4Sjoerg /// current language mode.
3781*e038c9c4Sjoerg if (!Result || !Notes.empty()) {
3782*e038c9c4Sjoerg Diag(E->getBeginLoc(), diag::err_attribute_argument_n_type)
3783*e038c9c4Sjoerg << CI << (Idx + 1) << AANT_ArgumentConstantExpr;
3784*e038c9c4Sjoerg for (auto &Note : Notes)
3785*e038c9c4Sjoerg Diag(Note.first, Note.second);
3786*e038c9c4Sjoerg return;
3787*e038c9c4Sjoerg }
3788*e038c9c4Sjoerg assert(Eval.Val.hasValue());
3789*e038c9c4Sjoerg E = ConstantExpr::Create(Context, E, Eval.Val);
3790*e038c9c4Sjoerg }
3791*e038c9c4Sjoerg D->addAttr(Attr);
3792*e038c9c4Sjoerg }
3793*e038c9c4Sjoerg
handleAnnotateAttr(Sema & S,Decl * D,const ParsedAttr & AL)37947330f729Sjoerg static void handleAnnotateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
3795*e038c9c4Sjoerg // Make sure that there is a string literal as the annotation's first
37967330f729Sjoerg // argument.
37977330f729Sjoerg StringRef Str;
37987330f729Sjoerg if (!S.checkStringLiteralArgumentAttr(AL, 0, Str))
37997330f729Sjoerg return;
38007330f729Sjoerg
3801*e038c9c4Sjoerg llvm::SmallVector<Expr *, 4> Args;
3802*e038c9c4Sjoerg Args.reserve(AL.getNumArgs() - 1);
3803*e038c9c4Sjoerg for (unsigned Idx = 1; Idx < AL.getNumArgs(); Idx++) {
3804*e038c9c4Sjoerg assert(!AL.isArgIdent(Idx));
3805*e038c9c4Sjoerg Args.push_back(AL.getArgAsExpr(Idx));
38067330f729Sjoerg }
38077330f729Sjoerg
3808*e038c9c4Sjoerg S.AddAnnotationAttr(D, AL, Str, Args);
38097330f729Sjoerg }
38107330f729Sjoerg
handleAlignValueAttr(Sema & S,Decl * D,const ParsedAttr & AL)38117330f729Sjoerg static void handleAlignValueAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
38127330f729Sjoerg S.AddAlignValueAttr(D, AL, AL.getArgAsExpr(0));
38137330f729Sjoerg }
38147330f729Sjoerg
AddAlignValueAttr(Decl * D,const AttributeCommonInfo & CI,Expr * E)38157330f729Sjoerg void Sema::AddAlignValueAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E) {
38167330f729Sjoerg AlignValueAttr TmpAttr(Context, CI, E);
38177330f729Sjoerg SourceLocation AttrLoc = CI.getLoc();
38187330f729Sjoerg
38197330f729Sjoerg QualType T;
38207330f729Sjoerg if (const auto *TD = dyn_cast<TypedefNameDecl>(D))
38217330f729Sjoerg T = TD->getUnderlyingType();
38227330f729Sjoerg else if (const auto *VD = dyn_cast<ValueDecl>(D))
38237330f729Sjoerg T = VD->getType();
38247330f729Sjoerg else
38257330f729Sjoerg llvm_unreachable("Unknown decl type for align_value");
38267330f729Sjoerg
38277330f729Sjoerg if (!T->isDependentType() && !T->isAnyPointerType() &&
38287330f729Sjoerg !T->isReferenceType() && !T->isMemberPointerType()) {
38297330f729Sjoerg Diag(AttrLoc, diag::warn_attribute_pointer_or_reference_only)
3830*e038c9c4Sjoerg << &TmpAttr << T << D->getSourceRange();
38317330f729Sjoerg return;
38327330f729Sjoerg }
38337330f729Sjoerg
38347330f729Sjoerg if (!E->isValueDependent()) {
38357330f729Sjoerg llvm::APSInt Alignment;
3836*e038c9c4Sjoerg ExprResult ICE = VerifyIntegerConstantExpression(
3837*e038c9c4Sjoerg E, &Alignment, diag::err_align_value_attribute_argument_not_int);
38387330f729Sjoerg if (ICE.isInvalid())
38397330f729Sjoerg return;
38407330f729Sjoerg
38417330f729Sjoerg if (!Alignment.isPowerOf2()) {
38427330f729Sjoerg Diag(AttrLoc, diag::err_alignment_not_power_of_two)
38437330f729Sjoerg << E->getSourceRange();
38447330f729Sjoerg return;
38457330f729Sjoerg }
38467330f729Sjoerg
38477330f729Sjoerg D->addAttr(::new (Context) AlignValueAttr(Context, CI, ICE.get()));
38487330f729Sjoerg return;
38497330f729Sjoerg }
38507330f729Sjoerg
38517330f729Sjoerg // Save dependent expressions in the AST to be instantiated.
38527330f729Sjoerg D->addAttr(::new (Context) AlignValueAttr(Context, CI, E));
38537330f729Sjoerg }
38547330f729Sjoerg
handleAlignedAttr(Sema & S,Decl * D,const ParsedAttr & AL)38557330f729Sjoerg static void handleAlignedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
38567330f729Sjoerg // check the attribute arguments.
38577330f729Sjoerg if (AL.getNumArgs() > 1) {
38587330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
38597330f729Sjoerg return;
38607330f729Sjoerg }
38617330f729Sjoerg
38627330f729Sjoerg if (AL.getNumArgs() == 0) {
38637330f729Sjoerg D->addAttr(::new (S.Context) AlignedAttr(S.Context, AL, true, nullptr));
38647330f729Sjoerg return;
38657330f729Sjoerg }
38667330f729Sjoerg
38677330f729Sjoerg Expr *E = AL.getArgAsExpr(0);
38687330f729Sjoerg if (AL.isPackExpansion() && !E->containsUnexpandedParameterPack()) {
38697330f729Sjoerg S.Diag(AL.getEllipsisLoc(),
38707330f729Sjoerg diag::err_pack_expansion_without_parameter_packs);
38717330f729Sjoerg return;
38727330f729Sjoerg }
38737330f729Sjoerg
38747330f729Sjoerg if (!AL.isPackExpansion() && S.DiagnoseUnexpandedParameterPack(E))
38757330f729Sjoerg return;
38767330f729Sjoerg
38777330f729Sjoerg S.AddAlignedAttr(D, AL, E, AL.isPackExpansion());
38787330f729Sjoerg }
38797330f729Sjoerg
AddAlignedAttr(Decl * D,const AttributeCommonInfo & CI,Expr * E,bool IsPackExpansion)38807330f729Sjoerg void Sema::AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
38817330f729Sjoerg bool IsPackExpansion) {
38827330f729Sjoerg AlignedAttr TmpAttr(Context, CI, true, E);
38837330f729Sjoerg SourceLocation AttrLoc = CI.getLoc();
38847330f729Sjoerg
38857330f729Sjoerg // C++11 alignas(...) and C11 _Alignas(...) have additional requirements.
38867330f729Sjoerg if (TmpAttr.isAlignas()) {
38877330f729Sjoerg // C++11 [dcl.align]p1:
38887330f729Sjoerg // An alignment-specifier may be applied to a variable or to a class
38897330f729Sjoerg // data member, but it shall not be applied to a bit-field, a function
38907330f729Sjoerg // parameter, the formal parameter of a catch clause, or a variable
38917330f729Sjoerg // declared with the register storage class specifier. An
38927330f729Sjoerg // alignment-specifier may also be applied to the declaration of a class
38937330f729Sjoerg // or enumeration type.
38947330f729Sjoerg // C11 6.7.5/2:
38957330f729Sjoerg // An alignment attribute shall not be specified in a declaration of
38967330f729Sjoerg // a typedef, or a bit-field, or a function, or a parameter, or an
38977330f729Sjoerg // object declared with the register storage-class specifier.
38987330f729Sjoerg int DiagKind = -1;
38997330f729Sjoerg if (isa<ParmVarDecl>(D)) {
39007330f729Sjoerg DiagKind = 0;
39017330f729Sjoerg } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
39027330f729Sjoerg if (VD->getStorageClass() == SC_Register)
39037330f729Sjoerg DiagKind = 1;
39047330f729Sjoerg if (VD->isExceptionVariable())
39057330f729Sjoerg DiagKind = 2;
39067330f729Sjoerg } else if (const auto *FD = dyn_cast<FieldDecl>(D)) {
39077330f729Sjoerg if (FD->isBitField())
39087330f729Sjoerg DiagKind = 3;
39097330f729Sjoerg } else if (!isa<TagDecl>(D)) {
39107330f729Sjoerg Diag(AttrLoc, diag::err_attribute_wrong_decl_type) << &TmpAttr
39117330f729Sjoerg << (TmpAttr.isC11() ? ExpectedVariableOrField
39127330f729Sjoerg : ExpectedVariableFieldOrTag);
39137330f729Sjoerg return;
39147330f729Sjoerg }
39157330f729Sjoerg if (DiagKind != -1) {
39167330f729Sjoerg Diag(AttrLoc, diag::err_alignas_attribute_wrong_decl_type)
39177330f729Sjoerg << &TmpAttr << DiagKind;
39187330f729Sjoerg return;
39197330f729Sjoerg }
39207330f729Sjoerg }
39217330f729Sjoerg
39227330f729Sjoerg if (E->isValueDependent()) {
39237330f729Sjoerg // We can't support a dependent alignment on a non-dependent type,
39247330f729Sjoerg // because we have no way to model that a type is "alignment-dependent"
39257330f729Sjoerg // but not dependent in any other way.
39267330f729Sjoerg if (const auto *TND = dyn_cast<TypedefNameDecl>(D)) {
39277330f729Sjoerg if (!TND->getUnderlyingType()->isDependentType()) {
39287330f729Sjoerg Diag(AttrLoc, diag::err_alignment_dependent_typedef_name)
39297330f729Sjoerg << E->getSourceRange();
39307330f729Sjoerg return;
39317330f729Sjoerg }
39327330f729Sjoerg }
39337330f729Sjoerg
39347330f729Sjoerg // Save dependent expressions in the AST to be instantiated.
39357330f729Sjoerg AlignedAttr *AA = ::new (Context) AlignedAttr(Context, CI, true, E);
39367330f729Sjoerg AA->setPackExpansion(IsPackExpansion);
39377330f729Sjoerg D->addAttr(AA);
39387330f729Sjoerg return;
39397330f729Sjoerg }
39407330f729Sjoerg
39417330f729Sjoerg // FIXME: Cache the number on the AL object?
39427330f729Sjoerg llvm::APSInt Alignment;
3943*e038c9c4Sjoerg ExprResult ICE = VerifyIntegerConstantExpression(
3944*e038c9c4Sjoerg E, &Alignment, diag::err_aligned_attribute_argument_not_int);
39457330f729Sjoerg if (ICE.isInvalid())
39467330f729Sjoerg return;
39477330f729Sjoerg
39487330f729Sjoerg uint64_t AlignVal = Alignment.getZExtValue();
39497330f729Sjoerg
39507330f729Sjoerg // C++11 [dcl.align]p2:
39517330f729Sjoerg // -- if the constant expression evaluates to zero, the alignment
39527330f729Sjoerg // specifier shall have no effect
39537330f729Sjoerg // C11 6.7.5p6:
39547330f729Sjoerg // An alignment specification of zero has no effect.
39557330f729Sjoerg if (!(TmpAttr.isAlignas() && !Alignment)) {
39567330f729Sjoerg if (!llvm::isPowerOf2_64(AlignVal)) {
39577330f729Sjoerg Diag(AttrLoc, diag::err_alignment_not_power_of_two)
39587330f729Sjoerg << E->getSourceRange();
39597330f729Sjoerg return;
39607330f729Sjoerg }
39617330f729Sjoerg }
39627330f729Sjoerg
3963*e038c9c4Sjoerg unsigned MaximumAlignment = Sema::MaximumAlignment;
3964*e038c9c4Sjoerg if (Context.getTargetInfo().getTriple().isOSBinFormatCOFF())
3965*e038c9c4Sjoerg MaximumAlignment = std::min(MaximumAlignment, 8192u);
3966*e038c9c4Sjoerg if (AlignVal > MaximumAlignment) {
3967*e038c9c4Sjoerg Diag(AttrLoc, diag::err_attribute_aligned_too_great)
3968*e038c9c4Sjoerg << MaximumAlignment << E->getSourceRange();
39697330f729Sjoerg return;
39707330f729Sjoerg }
39717330f729Sjoerg
39727330f729Sjoerg if (Context.getTargetInfo().isTLSSupported()) {
39737330f729Sjoerg unsigned MaxTLSAlign =
39747330f729Sjoerg Context.toCharUnitsFromBits(Context.getTargetInfo().getMaxTLSAlign())
39757330f729Sjoerg .getQuantity();
39767330f729Sjoerg const auto *VD = dyn_cast<VarDecl>(D);
39777330f729Sjoerg if (MaxTLSAlign && AlignVal > MaxTLSAlign && VD &&
39787330f729Sjoerg VD->getTLSKind() != VarDecl::TLS_None) {
39797330f729Sjoerg Diag(VD->getLocation(), diag::err_tls_var_aligned_over_maximum)
39807330f729Sjoerg << (unsigned)AlignVal << VD << MaxTLSAlign;
39817330f729Sjoerg return;
39827330f729Sjoerg }
39837330f729Sjoerg }
39847330f729Sjoerg
39857330f729Sjoerg AlignedAttr *AA = ::new (Context) AlignedAttr(Context, CI, true, ICE.get());
39867330f729Sjoerg AA->setPackExpansion(IsPackExpansion);
39877330f729Sjoerg D->addAttr(AA);
39887330f729Sjoerg }
39897330f729Sjoerg
AddAlignedAttr(Decl * D,const AttributeCommonInfo & CI,TypeSourceInfo * TS,bool IsPackExpansion)39907330f729Sjoerg void Sema::AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI,
39917330f729Sjoerg TypeSourceInfo *TS, bool IsPackExpansion) {
39927330f729Sjoerg // FIXME: Cache the number on the AL object if non-dependent?
39937330f729Sjoerg // FIXME: Perform checking of type validity
39947330f729Sjoerg AlignedAttr *AA = ::new (Context) AlignedAttr(Context, CI, false, TS);
39957330f729Sjoerg AA->setPackExpansion(IsPackExpansion);
39967330f729Sjoerg D->addAttr(AA);
39977330f729Sjoerg }
39987330f729Sjoerg
CheckAlignasUnderalignment(Decl * D)39997330f729Sjoerg void Sema::CheckAlignasUnderalignment(Decl *D) {
40007330f729Sjoerg assert(D->hasAttrs() && "no attributes on decl");
40017330f729Sjoerg
40027330f729Sjoerg QualType UnderlyingTy, DiagTy;
40037330f729Sjoerg if (const auto *VD = dyn_cast<ValueDecl>(D)) {
40047330f729Sjoerg UnderlyingTy = DiagTy = VD->getType();
40057330f729Sjoerg } else {
40067330f729Sjoerg UnderlyingTy = DiagTy = Context.getTagDeclType(cast<TagDecl>(D));
40077330f729Sjoerg if (const auto *ED = dyn_cast<EnumDecl>(D))
40087330f729Sjoerg UnderlyingTy = ED->getIntegerType();
40097330f729Sjoerg }
40107330f729Sjoerg if (DiagTy->isDependentType() || DiagTy->isIncompleteType())
40117330f729Sjoerg return;
40127330f729Sjoerg
40137330f729Sjoerg // C++11 [dcl.align]p5, C11 6.7.5/4:
40147330f729Sjoerg // The combined effect of all alignment attributes in a declaration shall
40157330f729Sjoerg // not specify an alignment that is less strict than the alignment that
40167330f729Sjoerg // would otherwise be required for the entity being declared.
40177330f729Sjoerg AlignedAttr *AlignasAttr = nullptr;
4018*e038c9c4Sjoerg AlignedAttr *LastAlignedAttr = nullptr;
40197330f729Sjoerg unsigned Align = 0;
40207330f729Sjoerg for (auto *I : D->specific_attrs<AlignedAttr>()) {
40217330f729Sjoerg if (I->isAlignmentDependent())
40227330f729Sjoerg return;
40237330f729Sjoerg if (I->isAlignas())
40247330f729Sjoerg AlignasAttr = I;
40257330f729Sjoerg Align = std::max(Align, I->getAlignment(Context));
4026*e038c9c4Sjoerg LastAlignedAttr = I;
40277330f729Sjoerg }
40287330f729Sjoerg
4029*e038c9c4Sjoerg if (Align && DiagTy->isSizelessType()) {
4030*e038c9c4Sjoerg Diag(LastAlignedAttr->getLocation(), diag::err_attribute_sizeless_type)
4031*e038c9c4Sjoerg << LastAlignedAttr << DiagTy;
4032*e038c9c4Sjoerg } else if (AlignasAttr && Align) {
40337330f729Sjoerg CharUnits RequestedAlign = Context.toCharUnitsFromBits(Align);
40347330f729Sjoerg CharUnits NaturalAlign = Context.getTypeAlignInChars(UnderlyingTy);
40357330f729Sjoerg if (NaturalAlign > RequestedAlign)
40367330f729Sjoerg Diag(AlignasAttr->getLocation(), diag::err_alignas_underaligned)
40377330f729Sjoerg << DiagTy << (unsigned)NaturalAlign.getQuantity();
40387330f729Sjoerg }
40397330f729Sjoerg }
40407330f729Sjoerg
checkMSInheritanceAttrOnDefinition(CXXRecordDecl * RD,SourceRange Range,bool BestCase,MSInheritanceModel ExplicitModel)40417330f729Sjoerg bool Sema::checkMSInheritanceAttrOnDefinition(
40427330f729Sjoerg CXXRecordDecl *RD, SourceRange Range, bool BestCase,
4043*e038c9c4Sjoerg MSInheritanceModel ExplicitModel) {
40447330f729Sjoerg assert(RD->hasDefinition() && "RD has no definition!");
40457330f729Sjoerg
40467330f729Sjoerg // We may not have seen base specifiers or any virtual methods yet. We will
40477330f729Sjoerg // have to wait until the record is defined to catch any mismatches.
40487330f729Sjoerg if (!RD->getDefinition()->isCompleteDefinition())
40497330f729Sjoerg return false;
40507330f729Sjoerg
40517330f729Sjoerg // The unspecified model never matches what a definition could need.
4052*e038c9c4Sjoerg if (ExplicitModel == MSInheritanceModel::Unspecified)
40537330f729Sjoerg return false;
40547330f729Sjoerg
40557330f729Sjoerg if (BestCase) {
4056*e038c9c4Sjoerg if (RD->calculateInheritanceModel() == ExplicitModel)
40577330f729Sjoerg return false;
40587330f729Sjoerg } else {
4059*e038c9c4Sjoerg if (RD->calculateInheritanceModel() <= ExplicitModel)
40607330f729Sjoerg return false;
40617330f729Sjoerg }
40627330f729Sjoerg
40637330f729Sjoerg Diag(Range.getBegin(), diag::err_mismatched_ms_inheritance)
40647330f729Sjoerg << 0 /*definition*/;
4065*e038c9c4Sjoerg Diag(RD->getDefinition()->getLocation(), diag::note_defined_here) << RD;
40667330f729Sjoerg return true;
40677330f729Sjoerg }
40687330f729Sjoerg
40697330f729Sjoerg /// parseModeAttrArg - Parses attribute mode string and returns parsed type
40707330f729Sjoerg /// attribute.
parseModeAttrArg(Sema & S,StringRef Str,unsigned & DestWidth,bool & IntegerMode,bool & ComplexMode,bool & ExplicitIEEE)40717330f729Sjoerg static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth,
4072*e038c9c4Sjoerg bool &IntegerMode, bool &ComplexMode,
4073*e038c9c4Sjoerg bool &ExplicitIEEE) {
40747330f729Sjoerg IntegerMode = true;
40757330f729Sjoerg ComplexMode = false;
40767330f729Sjoerg switch (Str.size()) {
40777330f729Sjoerg case 2:
40787330f729Sjoerg switch (Str[0]) {
40797330f729Sjoerg case 'Q':
40807330f729Sjoerg DestWidth = 8;
40817330f729Sjoerg break;
40827330f729Sjoerg case 'H':
40837330f729Sjoerg DestWidth = 16;
40847330f729Sjoerg break;
40857330f729Sjoerg case 'S':
40867330f729Sjoerg DestWidth = 32;
40877330f729Sjoerg break;
40887330f729Sjoerg case 'D':
40897330f729Sjoerg DestWidth = 64;
40907330f729Sjoerg break;
40917330f729Sjoerg case 'X':
40927330f729Sjoerg DestWidth = 96;
40937330f729Sjoerg break;
4094*e038c9c4Sjoerg case 'K': // KFmode - IEEE quad precision (__float128)
4095*e038c9c4Sjoerg ExplicitIEEE = true;
4096*e038c9c4Sjoerg DestWidth = Str[1] == 'I' ? 0 : 128;
4097*e038c9c4Sjoerg break;
40987330f729Sjoerg case 'T':
4099*e038c9c4Sjoerg ExplicitIEEE = false;
41007330f729Sjoerg DestWidth = 128;
41017330f729Sjoerg break;
41027330f729Sjoerg }
41037330f729Sjoerg if (Str[1] == 'F') {
41047330f729Sjoerg IntegerMode = false;
41057330f729Sjoerg } else if (Str[1] == 'C') {
41067330f729Sjoerg IntegerMode = false;
41077330f729Sjoerg ComplexMode = true;
41087330f729Sjoerg } else if (Str[1] != 'I') {
41097330f729Sjoerg DestWidth = 0;
41107330f729Sjoerg }
41117330f729Sjoerg break;
41127330f729Sjoerg case 4:
41137330f729Sjoerg // FIXME: glibc uses 'word' to define register_t; this is narrower than a
41147330f729Sjoerg // pointer on PIC16 and other embedded platforms.
41157330f729Sjoerg if (Str == "word")
41167330f729Sjoerg DestWidth = S.Context.getTargetInfo().getRegisterWidth();
41177330f729Sjoerg else if (Str == "byte")
41187330f729Sjoerg DestWidth = S.Context.getTargetInfo().getCharWidth();
41197330f729Sjoerg break;
41207330f729Sjoerg case 7:
41217330f729Sjoerg if (Str == "pointer")
41227330f729Sjoerg DestWidth = S.Context.getTargetInfo().getPointerWidth(0);
41237330f729Sjoerg break;
41247330f729Sjoerg case 11:
41257330f729Sjoerg if (Str == "unwind_word")
41267330f729Sjoerg DestWidth = S.Context.getTargetInfo().getUnwindWordWidth();
41277330f729Sjoerg break;
41287330f729Sjoerg }
41297330f729Sjoerg }
41307330f729Sjoerg
41317330f729Sjoerg /// handleModeAttr - This attribute modifies the width of a decl with primitive
41327330f729Sjoerg /// type.
41337330f729Sjoerg ///
41347330f729Sjoerg /// Despite what would be logical, the mode attribute is a decl attribute, not a
41357330f729Sjoerg /// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be
41367330f729Sjoerg /// HImode, not an intermediate pointer.
handleModeAttr(Sema & S,Decl * D,const ParsedAttr & AL)41377330f729Sjoerg static void handleModeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
41387330f729Sjoerg // This attribute isn't documented, but glibc uses it. It changes
41397330f729Sjoerg // the width of an int or unsigned int to the specified size.
41407330f729Sjoerg if (!AL.isArgIdent(0)) {
41417330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
41427330f729Sjoerg << AL << AANT_ArgumentIdentifier;
41437330f729Sjoerg return;
41447330f729Sjoerg }
41457330f729Sjoerg
41467330f729Sjoerg IdentifierInfo *Name = AL.getArgAsIdent(0)->Ident;
41477330f729Sjoerg
41487330f729Sjoerg S.AddModeAttr(D, AL, Name);
41497330f729Sjoerg }
41507330f729Sjoerg
AddModeAttr(Decl * D,const AttributeCommonInfo & CI,IdentifierInfo * Name,bool InInstantiation)41517330f729Sjoerg void Sema::AddModeAttr(Decl *D, const AttributeCommonInfo &CI,
41527330f729Sjoerg IdentifierInfo *Name, bool InInstantiation) {
41537330f729Sjoerg StringRef Str = Name->getName();
41547330f729Sjoerg normalizeName(Str);
41557330f729Sjoerg SourceLocation AttrLoc = CI.getLoc();
41567330f729Sjoerg
41577330f729Sjoerg unsigned DestWidth = 0;
41587330f729Sjoerg bool IntegerMode = true;
41597330f729Sjoerg bool ComplexMode = false;
4160*e038c9c4Sjoerg bool ExplicitIEEE = false;
41617330f729Sjoerg llvm::APInt VectorSize(64, 0);
41627330f729Sjoerg if (Str.size() >= 4 && Str[0] == 'V') {
41637330f729Sjoerg // Minimal length of vector mode is 4: 'V' + NUMBER(>=1) + TYPE(>=2).
41647330f729Sjoerg size_t StrSize = Str.size();
41657330f729Sjoerg size_t VectorStringLength = 0;
41667330f729Sjoerg while ((VectorStringLength + 1) < StrSize &&
41677330f729Sjoerg isdigit(Str[VectorStringLength + 1]))
41687330f729Sjoerg ++VectorStringLength;
41697330f729Sjoerg if (VectorStringLength &&
41707330f729Sjoerg !Str.substr(1, VectorStringLength).getAsInteger(10, VectorSize) &&
41717330f729Sjoerg VectorSize.isPowerOf2()) {
41727330f729Sjoerg parseModeAttrArg(*this, Str.substr(VectorStringLength + 1), DestWidth,
4173*e038c9c4Sjoerg IntegerMode, ComplexMode, ExplicitIEEE);
41747330f729Sjoerg // Avoid duplicate warning from template instantiation.
41757330f729Sjoerg if (!InInstantiation)
41767330f729Sjoerg Diag(AttrLoc, diag::warn_vector_mode_deprecated);
41777330f729Sjoerg } else {
41787330f729Sjoerg VectorSize = 0;
41797330f729Sjoerg }
41807330f729Sjoerg }
41817330f729Sjoerg
41827330f729Sjoerg if (!VectorSize)
4183*e038c9c4Sjoerg parseModeAttrArg(*this, Str, DestWidth, IntegerMode, ComplexMode,
4184*e038c9c4Sjoerg ExplicitIEEE);
41857330f729Sjoerg
41867330f729Sjoerg // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t
41877330f729Sjoerg // and friends, at least with glibc.
41887330f729Sjoerg // FIXME: Make sure floating-point mappings are accurate
41897330f729Sjoerg // FIXME: Support XF and TF types
41907330f729Sjoerg if (!DestWidth) {
41917330f729Sjoerg Diag(AttrLoc, diag::err_machine_mode) << 0 /*Unknown*/ << Name;
41927330f729Sjoerg return;
41937330f729Sjoerg }
41947330f729Sjoerg
41957330f729Sjoerg QualType OldTy;
41967330f729Sjoerg if (const auto *TD = dyn_cast<TypedefNameDecl>(D))
41977330f729Sjoerg OldTy = TD->getUnderlyingType();
41987330f729Sjoerg else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
41997330f729Sjoerg // Something like 'typedef enum { X } __attribute__((mode(XX))) T;'.
42007330f729Sjoerg // Try to get type from enum declaration, default to int.
42017330f729Sjoerg OldTy = ED->getIntegerType();
42027330f729Sjoerg if (OldTy.isNull())
42037330f729Sjoerg OldTy = Context.IntTy;
42047330f729Sjoerg } else
42057330f729Sjoerg OldTy = cast<ValueDecl>(D)->getType();
42067330f729Sjoerg
42077330f729Sjoerg if (OldTy->isDependentType()) {
42087330f729Sjoerg D->addAttr(::new (Context) ModeAttr(Context, CI, Name));
42097330f729Sjoerg return;
42107330f729Sjoerg }
42117330f729Sjoerg
42127330f729Sjoerg // Base type can also be a vector type (see PR17453).
42137330f729Sjoerg // Distinguish between base type and base element type.
42147330f729Sjoerg QualType OldElemTy = OldTy;
42157330f729Sjoerg if (const auto *VT = OldTy->getAs<VectorType>())
42167330f729Sjoerg OldElemTy = VT->getElementType();
42177330f729Sjoerg
42187330f729Sjoerg // GCC allows 'mode' attribute on enumeration types (even incomplete), except
42197330f729Sjoerg // for vector modes. So, 'enum X __attribute__((mode(QI)));' forms a complete
42207330f729Sjoerg // type, 'enum { A } __attribute__((mode(V4SI)))' is rejected.
42217330f729Sjoerg if ((isa<EnumDecl>(D) || OldElemTy->getAs<EnumType>()) &&
42227330f729Sjoerg VectorSize.getBoolValue()) {
42237330f729Sjoerg Diag(AttrLoc, diag::err_enum_mode_vector_type) << Name << CI.getRange();
42247330f729Sjoerg return;
42257330f729Sjoerg }
4226*e038c9c4Sjoerg bool IntegralOrAnyEnumType = (OldElemTy->isIntegralOrEnumerationType() &&
4227*e038c9c4Sjoerg !OldElemTy->isExtIntType()) ||
4228*e038c9c4Sjoerg OldElemTy->getAs<EnumType>();
42297330f729Sjoerg
42307330f729Sjoerg if (!OldElemTy->getAs<BuiltinType>() && !OldElemTy->isComplexType() &&
42317330f729Sjoerg !IntegralOrAnyEnumType)
42327330f729Sjoerg Diag(AttrLoc, diag::err_mode_not_primitive);
42337330f729Sjoerg else if (IntegerMode) {
42347330f729Sjoerg if (!IntegralOrAnyEnumType)
42357330f729Sjoerg Diag(AttrLoc, diag::err_mode_wrong_type);
42367330f729Sjoerg } else if (ComplexMode) {
42377330f729Sjoerg if (!OldElemTy->isComplexType())
42387330f729Sjoerg Diag(AttrLoc, diag::err_mode_wrong_type);
42397330f729Sjoerg } else {
42407330f729Sjoerg if (!OldElemTy->isFloatingType())
42417330f729Sjoerg Diag(AttrLoc, diag::err_mode_wrong_type);
42427330f729Sjoerg }
42437330f729Sjoerg
42447330f729Sjoerg QualType NewElemTy;
42457330f729Sjoerg
42467330f729Sjoerg if (IntegerMode)
42477330f729Sjoerg NewElemTy = Context.getIntTypeForBitwidth(DestWidth,
42487330f729Sjoerg OldElemTy->isSignedIntegerType());
42497330f729Sjoerg else
4250*e038c9c4Sjoerg NewElemTy = Context.getRealTypeForBitwidth(DestWidth, ExplicitIEEE);
42517330f729Sjoerg
42527330f729Sjoerg if (NewElemTy.isNull()) {
42537330f729Sjoerg Diag(AttrLoc, diag::err_machine_mode) << 1 /*Unsupported*/ << Name;
42547330f729Sjoerg return;
42557330f729Sjoerg }
42567330f729Sjoerg
42577330f729Sjoerg if (ComplexMode) {
42587330f729Sjoerg NewElemTy = Context.getComplexType(NewElemTy);
42597330f729Sjoerg }
42607330f729Sjoerg
42617330f729Sjoerg QualType NewTy = NewElemTy;
42627330f729Sjoerg if (VectorSize.getBoolValue()) {
42637330f729Sjoerg NewTy = Context.getVectorType(NewTy, VectorSize.getZExtValue(),
42647330f729Sjoerg VectorType::GenericVector);
42657330f729Sjoerg } else if (const auto *OldVT = OldTy->getAs<VectorType>()) {
42667330f729Sjoerg // Complex machine mode does not support base vector types.
42677330f729Sjoerg if (ComplexMode) {
42687330f729Sjoerg Diag(AttrLoc, diag::err_complex_mode_vector_type);
42697330f729Sjoerg return;
42707330f729Sjoerg }
42717330f729Sjoerg unsigned NumElements = Context.getTypeSize(OldElemTy) *
42727330f729Sjoerg OldVT->getNumElements() /
42737330f729Sjoerg Context.getTypeSize(NewElemTy);
42747330f729Sjoerg NewTy =
42757330f729Sjoerg Context.getVectorType(NewElemTy, NumElements, OldVT->getVectorKind());
42767330f729Sjoerg }
42777330f729Sjoerg
42787330f729Sjoerg if (NewTy.isNull()) {
42797330f729Sjoerg Diag(AttrLoc, diag::err_mode_wrong_type);
42807330f729Sjoerg return;
42817330f729Sjoerg }
42827330f729Sjoerg
42837330f729Sjoerg // Install the new type.
42847330f729Sjoerg if (auto *TD = dyn_cast<TypedefNameDecl>(D))
42857330f729Sjoerg TD->setModedTypeSourceInfo(TD->getTypeSourceInfo(), NewTy);
42867330f729Sjoerg else if (auto *ED = dyn_cast<EnumDecl>(D))
42877330f729Sjoerg ED->setIntegerType(NewTy);
42887330f729Sjoerg else
42897330f729Sjoerg cast<ValueDecl>(D)->setType(NewTy);
42907330f729Sjoerg
42917330f729Sjoerg D->addAttr(::new (Context) ModeAttr(Context, CI, Name));
42927330f729Sjoerg }
42937330f729Sjoerg
handleNoDebugAttr(Sema & S,Decl * D,const ParsedAttr & AL)42947330f729Sjoerg static void handleNoDebugAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
42957330f729Sjoerg D->addAttr(::new (S.Context) NoDebugAttr(S.Context, AL));
42967330f729Sjoerg }
42977330f729Sjoerg
mergeAlwaysInlineAttr(Decl * D,const AttributeCommonInfo & CI,const IdentifierInfo * Ident)42987330f729Sjoerg AlwaysInlineAttr *Sema::mergeAlwaysInlineAttr(Decl *D,
42997330f729Sjoerg const AttributeCommonInfo &CI,
43007330f729Sjoerg const IdentifierInfo *Ident) {
43017330f729Sjoerg if (OptimizeNoneAttr *Optnone = D->getAttr<OptimizeNoneAttr>()) {
43027330f729Sjoerg Diag(CI.getLoc(), diag::warn_attribute_ignored) << Ident;
43037330f729Sjoerg Diag(Optnone->getLocation(), diag::note_conflicting_attribute);
43047330f729Sjoerg return nullptr;
43057330f729Sjoerg }
43067330f729Sjoerg
43077330f729Sjoerg if (D->hasAttr<AlwaysInlineAttr>())
43087330f729Sjoerg return nullptr;
43097330f729Sjoerg
43107330f729Sjoerg return ::new (Context) AlwaysInlineAttr(Context, CI);
43117330f729Sjoerg }
43127330f729Sjoerg
mergeInternalLinkageAttr(Decl * D,const ParsedAttr & AL)43137330f729Sjoerg InternalLinkageAttr *Sema::mergeInternalLinkageAttr(Decl *D,
43147330f729Sjoerg const ParsedAttr &AL) {
43157330f729Sjoerg if (const auto *VD = dyn_cast<VarDecl>(D)) {
43167330f729Sjoerg // Attribute applies to Var but not any subclass of it (like ParmVar,
43177330f729Sjoerg // ImplicitParm or VarTemplateSpecialization).
43187330f729Sjoerg if (VD->getKind() != Decl::Var) {
43197330f729Sjoerg Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
43207330f729Sjoerg << AL << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass
43217330f729Sjoerg : ExpectedVariableOrFunction);
43227330f729Sjoerg return nullptr;
43237330f729Sjoerg }
43247330f729Sjoerg // Attribute does not apply to non-static local variables.
43257330f729Sjoerg if (VD->hasLocalStorage()) {
43267330f729Sjoerg Diag(VD->getLocation(), diag::warn_internal_linkage_local_storage);
43277330f729Sjoerg return nullptr;
43287330f729Sjoerg }
43297330f729Sjoerg }
43307330f729Sjoerg
43317330f729Sjoerg return ::new (Context) InternalLinkageAttr(Context, AL);
43327330f729Sjoerg }
43337330f729Sjoerg InternalLinkageAttr *
mergeInternalLinkageAttr(Decl * D,const InternalLinkageAttr & AL)43347330f729Sjoerg Sema::mergeInternalLinkageAttr(Decl *D, const InternalLinkageAttr &AL) {
43357330f729Sjoerg if (const auto *VD = dyn_cast<VarDecl>(D)) {
43367330f729Sjoerg // Attribute applies to Var but not any subclass of it (like ParmVar,
43377330f729Sjoerg // ImplicitParm or VarTemplateSpecialization).
43387330f729Sjoerg if (VD->getKind() != Decl::Var) {
43397330f729Sjoerg Diag(AL.getLocation(), diag::warn_attribute_wrong_decl_type)
43407330f729Sjoerg << &AL << (getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass
43417330f729Sjoerg : ExpectedVariableOrFunction);
43427330f729Sjoerg return nullptr;
43437330f729Sjoerg }
43447330f729Sjoerg // Attribute does not apply to non-static local variables.
43457330f729Sjoerg if (VD->hasLocalStorage()) {
43467330f729Sjoerg Diag(VD->getLocation(), diag::warn_internal_linkage_local_storage);
43477330f729Sjoerg return nullptr;
43487330f729Sjoerg }
43497330f729Sjoerg }
43507330f729Sjoerg
43517330f729Sjoerg return ::new (Context) InternalLinkageAttr(Context, AL);
43527330f729Sjoerg }
43537330f729Sjoerg
mergeMinSizeAttr(Decl * D,const AttributeCommonInfo & CI)43547330f729Sjoerg MinSizeAttr *Sema::mergeMinSizeAttr(Decl *D, const AttributeCommonInfo &CI) {
43557330f729Sjoerg if (OptimizeNoneAttr *Optnone = D->getAttr<OptimizeNoneAttr>()) {
43567330f729Sjoerg Diag(CI.getLoc(), diag::warn_attribute_ignored) << "'minsize'";
43577330f729Sjoerg Diag(Optnone->getLocation(), diag::note_conflicting_attribute);
43587330f729Sjoerg return nullptr;
43597330f729Sjoerg }
43607330f729Sjoerg
43617330f729Sjoerg if (D->hasAttr<MinSizeAttr>())
43627330f729Sjoerg return nullptr;
43637330f729Sjoerg
43647330f729Sjoerg return ::new (Context) MinSizeAttr(Context, CI);
43657330f729Sjoerg }
43667330f729Sjoerg
mergeSwiftNameAttr(Decl * D,const SwiftNameAttr & SNA,StringRef Name)4367*e038c9c4Sjoerg SwiftNameAttr *Sema::mergeSwiftNameAttr(Decl *D, const SwiftNameAttr &SNA,
4368*e038c9c4Sjoerg StringRef Name) {
4369*e038c9c4Sjoerg if (const auto *PrevSNA = D->getAttr<SwiftNameAttr>()) {
4370*e038c9c4Sjoerg if (PrevSNA->getName() != Name && !PrevSNA->isImplicit()) {
4371*e038c9c4Sjoerg Diag(PrevSNA->getLocation(), diag::err_attributes_are_not_compatible)
4372*e038c9c4Sjoerg << PrevSNA << &SNA;
4373*e038c9c4Sjoerg Diag(SNA.getLoc(), diag::note_conflicting_attribute);
4374*e038c9c4Sjoerg }
43757330f729Sjoerg
4376*e038c9c4Sjoerg D->dropAttr<SwiftNameAttr>();
4377*e038c9c4Sjoerg }
4378*e038c9c4Sjoerg return ::new (Context) SwiftNameAttr(Context, SNA, Name);
43797330f729Sjoerg }
43807330f729Sjoerg
mergeOptimizeNoneAttr(Decl * D,const AttributeCommonInfo & CI)43817330f729Sjoerg OptimizeNoneAttr *Sema::mergeOptimizeNoneAttr(Decl *D,
43827330f729Sjoerg const AttributeCommonInfo &CI) {
43837330f729Sjoerg if (AlwaysInlineAttr *Inline = D->getAttr<AlwaysInlineAttr>()) {
43847330f729Sjoerg Diag(Inline->getLocation(), diag::warn_attribute_ignored) << Inline;
43857330f729Sjoerg Diag(CI.getLoc(), diag::note_conflicting_attribute);
43867330f729Sjoerg D->dropAttr<AlwaysInlineAttr>();
43877330f729Sjoerg }
43887330f729Sjoerg if (MinSizeAttr *MinSize = D->getAttr<MinSizeAttr>()) {
43897330f729Sjoerg Diag(MinSize->getLocation(), diag::warn_attribute_ignored) << MinSize;
43907330f729Sjoerg Diag(CI.getLoc(), diag::note_conflicting_attribute);
43917330f729Sjoerg D->dropAttr<MinSizeAttr>();
43927330f729Sjoerg }
43937330f729Sjoerg
43947330f729Sjoerg if (D->hasAttr<OptimizeNoneAttr>())
43957330f729Sjoerg return nullptr;
43967330f729Sjoerg
43977330f729Sjoerg return ::new (Context) OptimizeNoneAttr(Context, CI);
43987330f729Sjoerg }
43997330f729Sjoerg
handleAlwaysInlineAttr(Sema & S,Decl * D,const ParsedAttr & AL)44007330f729Sjoerg static void handleAlwaysInlineAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
44017330f729Sjoerg if (AlwaysInlineAttr *Inline =
44027330f729Sjoerg S.mergeAlwaysInlineAttr(D, AL, AL.getAttrName()))
44037330f729Sjoerg D->addAttr(Inline);
44047330f729Sjoerg }
44057330f729Sjoerg
handleMinSizeAttr(Sema & S,Decl * D,const ParsedAttr & AL)44067330f729Sjoerg static void handleMinSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
44077330f729Sjoerg if (MinSizeAttr *MinSize = S.mergeMinSizeAttr(D, AL))
44087330f729Sjoerg D->addAttr(MinSize);
44097330f729Sjoerg }
44107330f729Sjoerg
handleOptimizeNoneAttr(Sema & S,Decl * D,const ParsedAttr & AL)44117330f729Sjoerg static void handleOptimizeNoneAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
44127330f729Sjoerg if (OptimizeNoneAttr *Optnone = S.mergeOptimizeNoneAttr(D, AL))
44137330f729Sjoerg D->addAttr(Optnone);
44147330f729Sjoerg }
44157330f729Sjoerg
handleConstantAttr(Sema & S,Decl * D,const ParsedAttr & AL)44167330f729Sjoerg static void handleConstantAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
44177330f729Sjoerg const auto *VD = cast<VarDecl>(D);
4418*e038c9c4Sjoerg if (VD->hasLocalStorage()) {
4419*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::err_cuda_nonstatic_constdev);
44207330f729Sjoerg return;
44217330f729Sjoerg }
4422*e038c9c4Sjoerg // constexpr variable may already get an implicit constant attr, which should
4423*e038c9c4Sjoerg // be replaced by the explicit constant attr.
4424*e038c9c4Sjoerg if (auto *A = D->getAttr<CUDAConstantAttr>()) {
4425*e038c9c4Sjoerg if (!A->isImplicit())
4426*e038c9c4Sjoerg return;
4427*e038c9c4Sjoerg D->dropAttr<CUDAConstantAttr>();
4428*e038c9c4Sjoerg }
44297330f729Sjoerg D->addAttr(::new (S.Context) CUDAConstantAttr(S.Context, AL));
44307330f729Sjoerg }
44317330f729Sjoerg
handleSharedAttr(Sema & S,Decl * D,const ParsedAttr & AL)44327330f729Sjoerg static void handleSharedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
44337330f729Sjoerg const auto *VD = cast<VarDecl>(D);
44347330f729Sjoerg // extern __shared__ is only allowed on arrays with no length (e.g.
44357330f729Sjoerg // "int x[]").
44367330f729Sjoerg if (!S.getLangOpts().GPURelocatableDeviceCode && VD->hasExternalStorage() &&
44377330f729Sjoerg !isa<IncompleteArrayType>(VD->getType())) {
44387330f729Sjoerg S.Diag(AL.getLoc(), diag::err_cuda_extern_shared) << VD;
44397330f729Sjoerg return;
44407330f729Sjoerg }
44417330f729Sjoerg if (S.getLangOpts().CUDA && VD->hasLocalStorage() &&
44427330f729Sjoerg S.CUDADiagIfHostCode(AL.getLoc(), diag::err_cuda_host_shared)
44437330f729Sjoerg << S.CurrentCUDATarget())
44447330f729Sjoerg return;
44457330f729Sjoerg D->addAttr(::new (S.Context) CUDASharedAttr(S.Context, AL));
44467330f729Sjoerg }
44477330f729Sjoerg
handleGlobalAttr(Sema & S,Decl * D,const ParsedAttr & AL)44487330f729Sjoerg static void handleGlobalAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
44497330f729Sjoerg const auto *FD = cast<FunctionDecl>(D);
44507330f729Sjoerg if (!FD->getReturnType()->isVoidType() &&
44517330f729Sjoerg !FD->getReturnType()->getAs<AutoType>() &&
44527330f729Sjoerg !FD->getReturnType()->isInstantiationDependentType()) {
44537330f729Sjoerg SourceRange RTRange = FD->getReturnTypeSourceRange();
44547330f729Sjoerg S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return)
44557330f729Sjoerg << FD->getType()
44567330f729Sjoerg << (RTRange.isValid() ? FixItHint::CreateReplacement(RTRange, "void")
44577330f729Sjoerg : FixItHint());
44587330f729Sjoerg return;
44597330f729Sjoerg }
44607330f729Sjoerg if (const auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
44617330f729Sjoerg if (Method->isInstance()) {
44627330f729Sjoerg S.Diag(Method->getBeginLoc(), diag::err_kern_is_nonstatic_method)
44637330f729Sjoerg << Method;
44647330f729Sjoerg return;
44657330f729Sjoerg }
44667330f729Sjoerg S.Diag(Method->getBeginLoc(), diag::warn_kern_is_method) << Method;
44677330f729Sjoerg }
44687330f729Sjoerg // Only warn for "inline" when compiling for host, to cut down on noise.
44697330f729Sjoerg if (FD->isInlineSpecified() && !S.getLangOpts().CUDAIsDevice)
44707330f729Sjoerg S.Diag(FD->getBeginLoc(), diag::warn_kern_is_inline) << FD;
44717330f729Sjoerg
44727330f729Sjoerg D->addAttr(::new (S.Context) CUDAGlobalAttr(S.Context, AL));
4473*e038c9c4Sjoerg // In host compilation the kernel is emitted as a stub function, which is
4474*e038c9c4Sjoerg // a helper function for launching the kernel. The instructions in the helper
4475*e038c9c4Sjoerg // function has nothing to do with the source code of the kernel. Do not emit
4476*e038c9c4Sjoerg // debug info for the stub function to avoid confusing the debugger.
4477*e038c9c4Sjoerg if (S.LangOpts.HIP && !S.LangOpts.CUDAIsDevice)
4478*e038c9c4Sjoerg D->addAttr(NoDebugAttr::CreateImplicit(S.Context));
4479*e038c9c4Sjoerg }
4480*e038c9c4Sjoerg
handleDeviceAttr(Sema & S,Decl * D,const ParsedAttr & AL)4481*e038c9c4Sjoerg static void handleDeviceAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
4482*e038c9c4Sjoerg if (const auto *VD = dyn_cast<VarDecl>(D)) {
4483*e038c9c4Sjoerg if (VD->hasLocalStorage()) {
4484*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::err_cuda_nonstatic_constdev);
4485*e038c9c4Sjoerg return;
4486*e038c9c4Sjoerg }
4487*e038c9c4Sjoerg }
4488*e038c9c4Sjoerg
4489*e038c9c4Sjoerg if (auto *A = D->getAttr<CUDADeviceAttr>()) {
4490*e038c9c4Sjoerg if (!A->isImplicit())
4491*e038c9c4Sjoerg return;
4492*e038c9c4Sjoerg D->dropAttr<CUDADeviceAttr>();
4493*e038c9c4Sjoerg }
4494*e038c9c4Sjoerg D->addAttr(::new (S.Context) CUDADeviceAttr(S.Context, AL));
4495*e038c9c4Sjoerg }
4496*e038c9c4Sjoerg
handleManagedAttr(Sema & S,Decl * D,const ParsedAttr & AL)4497*e038c9c4Sjoerg static void handleManagedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
4498*e038c9c4Sjoerg if (const auto *VD = dyn_cast<VarDecl>(D)) {
4499*e038c9c4Sjoerg if (VD->hasLocalStorage()) {
4500*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::err_cuda_nonstatic_constdev);
4501*e038c9c4Sjoerg return;
4502*e038c9c4Sjoerg }
4503*e038c9c4Sjoerg }
4504*e038c9c4Sjoerg if (!D->hasAttr<HIPManagedAttr>())
4505*e038c9c4Sjoerg D->addAttr(::new (S.Context) HIPManagedAttr(S.Context, AL));
4506*e038c9c4Sjoerg if (!D->hasAttr<CUDADeviceAttr>())
4507*e038c9c4Sjoerg D->addAttr(CUDADeviceAttr::CreateImplicit(S.Context));
45087330f729Sjoerg }
45097330f729Sjoerg
handleGNUInlineAttr(Sema & S,Decl * D,const ParsedAttr & AL)45107330f729Sjoerg static void handleGNUInlineAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
45117330f729Sjoerg const auto *Fn = cast<FunctionDecl>(D);
45127330f729Sjoerg if (!Fn->isInlineSpecified()) {
45137330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_gnu_inline_attribute_requires_inline);
45147330f729Sjoerg return;
45157330f729Sjoerg }
45167330f729Sjoerg
45177330f729Sjoerg if (S.LangOpts.CPlusPlus && Fn->getStorageClass() != SC_Extern)
45187330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_gnu_inline_cplusplus_without_extern);
45197330f729Sjoerg
45207330f729Sjoerg D->addAttr(::new (S.Context) GNUInlineAttr(S.Context, AL));
45217330f729Sjoerg }
45227330f729Sjoerg
handleCallConvAttr(Sema & S,Decl * D,const ParsedAttr & AL)45237330f729Sjoerg static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
45247330f729Sjoerg if (hasDeclarator(D)) return;
45257330f729Sjoerg
45267330f729Sjoerg // Diagnostic is emitted elsewhere: here we store the (valid) AL
45277330f729Sjoerg // in the Decl node for syntactic reasoning, e.g., pretty-printing.
45287330f729Sjoerg CallingConv CC;
45297330f729Sjoerg if (S.CheckCallingConvAttr(AL, CC, /*FD*/nullptr))
45307330f729Sjoerg return;
45317330f729Sjoerg
45327330f729Sjoerg if (!isa<ObjCMethodDecl>(D)) {
45337330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
45347330f729Sjoerg << AL << ExpectedFunctionOrMethod;
45357330f729Sjoerg return;
45367330f729Sjoerg }
45377330f729Sjoerg
45387330f729Sjoerg switch (AL.getKind()) {
45397330f729Sjoerg case ParsedAttr::AT_FastCall:
45407330f729Sjoerg D->addAttr(::new (S.Context) FastCallAttr(S.Context, AL));
45417330f729Sjoerg return;
45427330f729Sjoerg case ParsedAttr::AT_StdCall:
45437330f729Sjoerg D->addAttr(::new (S.Context) StdCallAttr(S.Context, AL));
45447330f729Sjoerg return;
45457330f729Sjoerg case ParsedAttr::AT_ThisCall:
45467330f729Sjoerg D->addAttr(::new (S.Context) ThisCallAttr(S.Context, AL));
45477330f729Sjoerg return;
45487330f729Sjoerg case ParsedAttr::AT_CDecl:
45497330f729Sjoerg D->addAttr(::new (S.Context) CDeclAttr(S.Context, AL));
45507330f729Sjoerg return;
45517330f729Sjoerg case ParsedAttr::AT_Pascal:
45527330f729Sjoerg D->addAttr(::new (S.Context) PascalAttr(S.Context, AL));
45537330f729Sjoerg return;
45547330f729Sjoerg case ParsedAttr::AT_SwiftCall:
45557330f729Sjoerg D->addAttr(::new (S.Context) SwiftCallAttr(S.Context, AL));
45567330f729Sjoerg return;
45577330f729Sjoerg case ParsedAttr::AT_VectorCall:
45587330f729Sjoerg D->addAttr(::new (S.Context) VectorCallAttr(S.Context, AL));
45597330f729Sjoerg return;
45607330f729Sjoerg case ParsedAttr::AT_MSABI:
45617330f729Sjoerg D->addAttr(::new (S.Context) MSABIAttr(S.Context, AL));
45627330f729Sjoerg return;
45637330f729Sjoerg case ParsedAttr::AT_SysVABI:
45647330f729Sjoerg D->addAttr(::new (S.Context) SysVABIAttr(S.Context, AL));
45657330f729Sjoerg return;
45667330f729Sjoerg case ParsedAttr::AT_RegCall:
45677330f729Sjoerg D->addAttr(::new (S.Context) RegCallAttr(S.Context, AL));
45687330f729Sjoerg return;
45697330f729Sjoerg case ParsedAttr::AT_Pcs: {
45707330f729Sjoerg PcsAttr::PCSType PCS;
45717330f729Sjoerg switch (CC) {
45727330f729Sjoerg case CC_AAPCS:
45737330f729Sjoerg PCS = PcsAttr::AAPCS;
45747330f729Sjoerg break;
45757330f729Sjoerg case CC_AAPCS_VFP:
45767330f729Sjoerg PCS = PcsAttr::AAPCS_VFP;
45777330f729Sjoerg break;
45787330f729Sjoerg default:
45797330f729Sjoerg llvm_unreachable("unexpected calling convention in pcs attribute");
45807330f729Sjoerg }
45817330f729Sjoerg
45827330f729Sjoerg D->addAttr(::new (S.Context) PcsAttr(S.Context, AL, PCS));
45837330f729Sjoerg return;
45847330f729Sjoerg }
45857330f729Sjoerg case ParsedAttr::AT_AArch64VectorPcs:
45867330f729Sjoerg D->addAttr(::new (S.Context) AArch64VectorPcsAttr(S.Context, AL));
45877330f729Sjoerg return;
45887330f729Sjoerg case ParsedAttr::AT_IntelOclBicc:
45897330f729Sjoerg D->addAttr(::new (S.Context) IntelOclBiccAttr(S.Context, AL));
45907330f729Sjoerg return;
45917330f729Sjoerg case ParsedAttr::AT_PreserveMost:
45927330f729Sjoerg D->addAttr(::new (S.Context) PreserveMostAttr(S.Context, AL));
45937330f729Sjoerg return;
45947330f729Sjoerg case ParsedAttr::AT_PreserveAll:
45957330f729Sjoerg D->addAttr(::new (S.Context) PreserveAllAttr(S.Context, AL));
45967330f729Sjoerg return;
45977330f729Sjoerg default:
45987330f729Sjoerg llvm_unreachable("unexpected attribute kind");
45997330f729Sjoerg }
46007330f729Sjoerg }
46017330f729Sjoerg
handleSuppressAttr(Sema & S,Decl * D,const ParsedAttr & AL)46027330f729Sjoerg static void handleSuppressAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
4603*e038c9c4Sjoerg if (!AL.checkAtLeastNumArgs(S, 1))
46047330f729Sjoerg return;
46057330f729Sjoerg
46067330f729Sjoerg std::vector<StringRef> DiagnosticIdentifiers;
46077330f729Sjoerg for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
46087330f729Sjoerg StringRef RuleName;
46097330f729Sjoerg
46107330f729Sjoerg if (!S.checkStringLiteralArgumentAttr(AL, I, RuleName, nullptr))
46117330f729Sjoerg return;
46127330f729Sjoerg
46137330f729Sjoerg // FIXME: Warn if the rule name is unknown. This is tricky because only
46147330f729Sjoerg // clang-tidy knows about available rules.
46157330f729Sjoerg DiagnosticIdentifiers.push_back(RuleName);
46167330f729Sjoerg }
46177330f729Sjoerg D->addAttr(::new (S.Context)
46187330f729Sjoerg SuppressAttr(S.Context, AL, DiagnosticIdentifiers.data(),
46197330f729Sjoerg DiagnosticIdentifiers.size()));
46207330f729Sjoerg }
46217330f729Sjoerg
handleLifetimeCategoryAttr(Sema & S,Decl * D,const ParsedAttr & AL)46227330f729Sjoerg static void handleLifetimeCategoryAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
46237330f729Sjoerg TypeSourceInfo *DerefTypeLoc = nullptr;
46247330f729Sjoerg QualType ParmType;
46257330f729Sjoerg if (AL.hasParsedType()) {
46267330f729Sjoerg ParmType = S.GetTypeFromParser(AL.getTypeArg(), &DerefTypeLoc);
46277330f729Sjoerg
46287330f729Sjoerg unsigned SelectIdx = ~0U;
4629*e038c9c4Sjoerg if (ParmType->isReferenceType())
46307330f729Sjoerg SelectIdx = 0;
46317330f729Sjoerg else if (ParmType->isArrayType())
4632*e038c9c4Sjoerg SelectIdx = 1;
46337330f729Sjoerg
46347330f729Sjoerg if (SelectIdx != ~0U) {
46357330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_invalid_argument)
46367330f729Sjoerg << SelectIdx << AL;
46377330f729Sjoerg return;
46387330f729Sjoerg }
46397330f729Sjoerg }
46407330f729Sjoerg
46417330f729Sjoerg // To check if earlier decl attributes do not conflict the newly parsed ones
4642*e038c9c4Sjoerg // we always add (and check) the attribute to the cannonical decl. We need
4643*e038c9c4Sjoerg // to repeat the check for attribute mutual exclusion because we're attaching
4644*e038c9c4Sjoerg // all of the attributes to the canonical declaration rather than the current
4645*e038c9c4Sjoerg // declaration.
46467330f729Sjoerg D = D->getCanonicalDecl();
46477330f729Sjoerg if (AL.getKind() == ParsedAttr::AT_Owner) {
46487330f729Sjoerg if (checkAttrMutualExclusion<PointerAttr>(S, D, AL))
46497330f729Sjoerg return;
46507330f729Sjoerg if (const auto *OAttr = D->getAttr<OwnerAttr>()) {
46517330f729Sjoerg const Type *ExistingDerefType = OAttr->getDerefTypeLoc()
46527330f729Sjoerg ? OAttr->getDerefType().getTypePtr()
46537330f729Sjoerg : nullptr;
46547330f729Sjoerg if (ExistingDerefType != ParmType.getTypePtrOrNull()) {
46557330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
46567330f729Sjoerg << AL << OAttr;
46577330f729Sjoerg S.Diag(OAttr->getLocation(), diag::note_conflicting_attribute);
46587330f729Sjoerg }
46597330f729Sjoerg return;
46607330f729Sjoerg }
46617330f729Sjoerg for (Decl *Redecl : D->redecls()) {
46627330f729Sjoerg Redecl->addAttr(::new (S.Context) OwnerAttr(S.Context, AL, DerefTypeLoc));
46637330f729Sjoerg }
46647330f729Sjoerg } else {
46657330f729Sjoerg if (checkAttrMutualExclusion<OwnerAttr>(S, D, AL))
46667330f729Sjoerg return;
46677330f729Sjoerg if (const auto *PAttr = D->getAttr<PointerAttr>()) {
46687330f729Sjoerg const Type *ExistingDerefType = PAttr->getDerefTypeLoc()
46697330f729Sjoerg ? PAttr->getDerefType().getTypePtr()
46707330f729Sjoerg : nullptr;
46717330f729Sjoerg if (ExistingDerefType != ParmType.getTypePtrOrNull()) {
46727330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
46737330f729Sjoerg << AL << PAttr;
46747330f729Sjoerg S.Diag(PAttr->getLocation(), diag::note_conflicting_attribute);
46757330f729Sjoerg }
46767330f729Sjoerg return;
46777330f729Sjoerg }
46787330f729Sjoerg for (Decl *Redecl : D->redecls()) {
46797330f729Sjoerg Redecl->addAttr(::new (S.Context)
46807330f729Sjoerg PointerAttr(S.Context, AL, DerefTypeLoc));
46817330f729Sjoerg }
46827330f729Sjoerg }
46837330f729Sjoerg }
46847330f729Sjoerg
CheckCallingConvAttr(const ParsedAttr & Attrs,CallingConv & CC,const FunctionDecl * FD)46857330f729Sjoerg bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC,
46867330f729Sjoerg const FunctionDecl *FD) {
46877330f729Sjoerg if (Attrs.isInvalid())
46887330f729Sjoerg return true;
46897330f729Sjoerg
46907330f729Sjoerg if (Attrs.hasProcessingCache()) {
46917330f729Sjoerg CC = (CallingConv) Attrs.getProcessingCache();
46927330f729Sjoerg return false;
46937330f729Sjoerg }
46947330f729Sjoerg
46957330f729Sjoerg unsigned ReqArgs = Attrs.getKind() == ParsedAttr::AT_Pcs ? 1 : 0;
4696*e038c9c4Sjoerg if (!Attrs.checkExactlyNumArgs(*this, ReqArgs)) {
46977330f729Sjoerg Attrs.setInvalid();
46987330f729Sjoerg return true;
46997330f729Sjoerg }
47007330f729Sjoerg
47017330f729Sjoerg // TODO: diagnose uses of these conventions on the wrong target.
47027330f729Sjoerg switch (Attrs.getKind()) {
47037330f729Sjoerg case ParsedAttr::AT_CDecl:
47047330f729Sjoerg CC = CC_C;
47057330f729Sjoerg break;
47067330f729Sjoerg case ParsedAttr::AT_FastCall:
47077330f729Sjoerg CC = CC_X86FastCall;
47087330f729Sjoerg break;
47097330f729Sjoerg case ParsedAttr::AT_StdCall:
47107330f729Sjoerg CC = CC_X86StdCall;
47117330f729Sjoerg break;
47127330f729Sjoerg case ParsedAttr::AT_ThisCall:
47137330f729Sjoerg CC = CC_X86ThisCall;
47147330f729Sjoerg break;
47157330f729Sjoerg case ParsedAttr::AT_Pascal:
47167330f729Sjoerg CC = CC_X86Pascal;
47177330f729Sjoerg break;
47187330f729Sjoerg case ParsedAttr::AT_SwiftCall:
47197330f729Sjoerg CC = CC_Swift;
47207330f729Sjoerg break;
47217330f729Sjoerg case ParsedAttr::AT_VectorCall:
47227330f729Sjoerg CC = CC_X86VectorCall;
47237330f729Sjoerg break;
47247330f729Sjoerg case ParsedAttr::AT_AArch64VectorPcs:
47257330f729Sjoerg CC = CC_AArch64VectorCall;
47267330f729Sjoerg break;
47277330f729Sjoerg case ParsedAttr::AT_RegCall:
47287330f729Sjoerg CC = CC_X86RegCall;
47297330f729Sjoerg break;
47307330f729Sjoerg case ParsedAttr::AT_MSABI:
47317330f729Sjoerg CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_C :
47327330f729Sjoerg CC_Win64;
47337330f729Sjoerg break;
47347330f729Sjoerg case ParsedAttr::AT_SysVABI:
47357330f729Sjoerg CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_X86_64SysV :
47367330f729Sjoerg CC_C;
47377330f729Sjoerg break;
47387330f729Sjoerg case ParsedAttr::AT_Pcs: {
47397330f729Sjoerg StringRef StrRef;
47407330f729Sjoerg if (!checkStringLiteralArgumentAttr(Attrs, 0, StrRef)) {
47417330f729Sjoerg Attrs.setInvalid();
47427330f729Sjoerg return true;
47437330f729Sjoerg }
47447330f729Sjoerg if (StrRef == "aapcs") {
47457330f729Sjoerg CC = CC_AAPCS;
47467330f729Sjoerg break;
47477330f729Sjoerg } else if (StrRef == "aapcs-vfp") {
47487330f729Sjoerg CC = CC_AAPCS_VFP;
47497330f729Sjoerg break;
47507330f729Sjoerg }
47517330f729Sjoerg
47527330f729Sjoerg Attrs.setInvalid();
47537330f729Sjoerg Diag(Attrs.getLoc(), diag::err_invalid_pcs);
47547330f729Sjoerg return true;
47557330f729Sjoerg }
47567330f729Sjoerg case ParsedAttr::AT_IntelOclBicc:
47577330f729Sjoerg CC = CC_IntelOclBicc;
47587330f729Sjoerg break;
47597330f729Sjoerg case ParsedAttr::AT_PreserveMost:
47607330f729Sjoerg CC = CC_PreserveMost;
47617330f729Sjoerg break;
47627330f729Sjoerg case ParsedAttr::AT_PreserveAll:
47637330f729Sjoerg CC = CC_PreserveAll;
47647330f729Sjoerg break;
47657330f729Sjoerg default: llvm_unreachable("unexpected attribute kind");
47667330f729Sjoerg }
47677330f729Sjoerg
47687330f729Sjoerg TargetInfo::CallingConvCheckResult A = TargetInfo::CCCR_OK;
47697330f729Sjoerg const TargetInfo &TI = Context.getTargetInfo();
47707330f729Sjoerg // CUDA functions may have host and/or device attributes which indicate
47717330f729Sjoerg // their targeted execution environment, therefore the calling convention
47727330f729Sjoerg // of functions in CUDA should be checked against the target deduced based
47737330f729Sjoerg // on their host/device attributes.
47747330f729Sjoerg if (LangOpts.CUDA) {
47757330f729Sjoerg auto *Aux = Context.getAuxTargetInfo();
47767330f729Sjoerg auto CudaTarget = IdentifyCUDATarget(FD);
47777330f729Sjoerg bool CheckHost = false, CheckDevice = false;
47787330f729Sjoerg switch (CudaTarget) {
47797330f729Sjoerg case CFT_HostDevice:
47807330f729Sjoerg CheckHost = true;
47817330f729Sjoerg CheckDevice = true;
47827330f729Sjoerg break;
47837330f729Sjoerg case CFT_Host:
47847330f729Sjoerg CheckHost = true;
47857330f729Sjoerg break;
47867330f729Sjoerg case CFT_Device:
47877330f729Sjoerg case CFT_Global:
47887330f729Sjoerg CheckDevice = true;
47897330f729Sjoerg break;
47907330f729Sjoerg case CFT_InvalidTarget:
47917330f729Sjoerg llvm_unreachable("unexpected cuda target");
47927330f729Sjoerg }
47937330f729Sjoerg auto *HostTI = LangOpts.CUDAIsDevice ? Aux : &TI;
47947330f729Sjoerg auto *DeviceTI = LangOpts.CUDAIsDevice ? &TI : Aux;
47957330f729Sjoerg if (CheckHost && HostTI)
47967330f729Sjoerg A = HostTI->checkCallingConvention(CC);
47977330f729Sjoerg if (A == TargetInfo::CCCR_OK && CheckDevice && DeviceTI)
47987330f729Sjoerg A = DeviceTI->checkCallingConvention(CC);
47997330f729Sjoerg } else {
48007330f729Sjoerg A = TI.checkCallingConvention(CC);
48017330f729Sjoerg }
48027330f729Sjoerg
48037330f729Sjoerg switch (A) {
48047330f729Sjoerg case TargetInfo::CCCR_OK:
48057330f729Sjoerg break;
48067330f729Sjoerg
48077330f729Sjoerg case TargetInfo::CCCR_Ignore:
48087330f729Sjoerg // Treat an ignored convention as if it was an explicit C calling convention
48097330f729Sjoerg // attribute. For example, __stdcall on Win x64 functions as __cdecl, so
48107330f729Sjoerg // that command line flags that change the default convention to
48117330f729Sjoerg // __vectorcall don't affect declarations marked __stdcall.
48127330f729Sjoerg CC = CC_C;
48137330f729Sjoerg break;
48147330f729Sjoerg
48157330f729Sjoerg case TargetInfo::CCCR_Error:
48167330f729Sjoerg Diag(Attrs.getLoc(), diag::error_cconv_unsupported)
48177330f729Sjoerg << Attrs << (int)CallingConventionIgnoredReason::ForThisTarget;
48187330f729Sjoerg break;
48197330f729Sjoerg
48207330f729Sjoerg case TargetInfo::CCCR_Warning: {
48217330f729Sjoerg Diag(Attrs.getLoc(), diag::warn_cconv_unsupported)
48227330f729Sjoerg << Attrs << (int)CallingConventionIgnoredReason::ForThisTarget;
48237330f729Sjoerg
48247330f729Sjoerg // This convention is not valid for the target. Use the default function or
48257330f729Sjoerg // method calling convention.
48267330f729Sjoerg bool IsCXXMethod = false, IsVariadic = false;
48277330f729Sjoerg if (FD) {
48287330f729Sjoerg IsCXXMethod = FD->isCXXInstanceMember();
48297330f729Sjoerg IsVariadic = FD->isVariadic();
48307330f729Sjoerg }
48317330f729Sjoerg CC = Context.getDefaultCallingConvention(IsVariadic, IsCXXMethod);
48327330f729Sjoerg break;
48337330f729Sjoerg }
48347330f729Sjoerg }
48357330f729Sjoerg
48367330f729Sjoerg Attrs.setProcessingCache((unsigned) CC);
48377330f729Sjoerg return false;
48387330f729Sjoerg }
48397330f729Sjoerg
48407330f729Sjoerg /// Pointer-like types in the default address space.
isValidSwiftContextType(QualType Ty)48417330f729Sjoerg static bool isValidSwiftContextType(QualType Ty) {
48427330f729Sjoerg if (!Ty->hasPointerRepresentation())
48437330f729Sjoerg return Ty->isDependentType();
48447330f729Sjoerg return Ty->getPointeeType().getAddressSpace() == LangAS::Default;
48457330f729Sjoerg }
48467330f729Sjoerg
48477330f729Sjoerg /// Pointers and references in the default address space.
isValidSwiftIndirectResultType(QualType Ty)48487330f729Sjoerg static bool isValidSwiftIndirectResultType(QualType Ty) {
48497330f729Sjoerg if (const auto *PtrType = Ty->getAs<PointerType>()) {
48507330f729Sjoerg Ty = PtrType->getPointeeType();
48517330f729Sjoerg } else if (const auto *RefType = Ty->getAs<ReferenceType>()) {
48527330f729Sjoerg Ty = RefType->getPointeeType();
48537330f729Sjoerg } else {
48547330f729Sjoerg return Ty->isDependentType();
48557330f729Sjoerg }
48567330f729Sjoerg return Ty.getAddressSpace() == LangAS::Default;
48577330f729Sjoerg }
48587330f729Sjoerg
48597330f729Sjoerg /// Pointers and references to pointers in the default address space.
isValidSwiftErrorResultType(QualType Ty)48607330f729Sjoerg static bool isValidSwiftErrorResultType(QualType Ty) {
48617330f729Sjoerg if (const auto *PtrType = Ty->getAs<PointerType>()) {
48627330f729Sjoerg Ty = PtrType->getPointeeType();
48637330f729Sjoerg } else if (const auto *RefType = Ty->getAs<ReferenceType>()) {
48647330f729Sjoerg Ty = RefType->getPointeeType();
48657330f729Sjoerg } else {
48667330f729Sjoerg return Ty->isDependentType();
48677330f729Sjoerg }
48687330f729Sjoerg if (!Ty.getQualifiers().empty())
48697330f729Sjoerg return false;
48707330f729Sjoerg return isValidSwiftContextType(Ty);
48717330f729Sjoerg }
48727330f729Sjoerg
AddParameterABIAttr(Decl * D,const AttributeCommonInfo & CI,ParameterABI abi)48737330f729Sjoerg void Sema::AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI,
48747330f729Sjoerg ParameterABI abi) {
48757330f729Sjoerg
48767330f729Sjoerg QualType type = cast<ParmVarDecl>(D)->getType();
48777330f729Sjoerg
48787330f729Sjoerg if (auto existingAttr = D->getAttr<ParameterABIAttr>()) {
48797330f729Sjoerg if (existingAttr->getABI() != abi) {
48807330f729Sjoerg Diag(CI.getLoc(), diag::err_attributes_are_not_compatible)
48817330f729Sjoerg << getParameterABISpelling(abi) << existingAttr;
48827330f729Sjoerg Diag(existingAttr->getLocation(), diag::note_conflicting_attribute);
48837330f729Sjoerg return;
48847330f729Sjoerg }
48857330f729Sjoerg }
48867330f729Sjoerg
48877330f729Sjoerg switch (abi) {
48887330f729Sjoerg case ParameterABI::Ordinary:
48897330f729Sjoerg llvm_unreachable("explicit attribute for ordinary parameter ABI?");
48907330f729Sjoerg
48917330f729Sjoerg case ParameterABI::SwiftContext:
48927330f729Sjoerg if (!isValidSwiftContextType(type)) {
48937330f729Sjoerg Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
48947330f729Sjoerg << getParameterABISpelling(abi) << /*pointer to pointer */ 0 << type;
48957330f729Sjoerg }
48967330f729Sjoerg D->addAttr(::new (Context) SwiftContextAttr(Context, CI));
48977330f729Sjoerg return;
48987330f729Sjoerg
48997330f729Sjoerg case ParameterABI::SwiftErrorResult:
49007330f729Sjoerg if (!isValidSwiftErrorResultType(type)) {
49017330f729Sjoerg Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
49027330f729Sjoerg << getParameterABISpelling(abi) << /*pointer to pointer */ 1 << type;
49037330f729Sjoerg }
49047330f729Sjoerg D->addAttr(::new (Context) SwiftErrorResultAttr(Context, CI));
49057330f729Sjoerg return;
49067330f729Sjoerg
49077330f729Sjoerg case ParameterABI::SwiftIndirectResult:
49087330f729Sjoerg if (!isValidSwiftIndirectResultType(type)) {
49097330f729Sjoerg Diag(CI.getLoc(), diag::err_swift_abi_parameter_wrong_type)
49107330f729Sjoerg << getParameterABISpelling(abi) << /*pointer*/ 0 << type;
49117330f729Sjoerg }
49127330f729Sjoerg D->addAttr(::new (Context) SwiftIndirectResultAttr(Context, CI));
49137330f729Sjoerg return;
49147330f729Sjoerg }
49157330f729Sjoerg llvm_unreachable("bad parameter ABI attribute");
49167330f729Sjoerg }
49177330f729Sjoerg
49187330f729Sjoerg /// Checks a regparm attribute, returning true if it is ill-formed and
49197330f729Sjoerg /// otherwise setting numParams to the appropriate value.
CheckRegparmAttr(const ParsedAttr & AL,unsigned & numParams)49207330f729Sjoerg bool Sema::CheckRegparmAttr(const ParsedAttr &AL, unsigned &numParams) {
49217330f729Sjoerg if (AL.isInvalid())
49227330f729Sjoerg return true;
49237330f729Sjoerg
4924*e038c9c4Sjoerg if (!AL.checkExactlyNumArgs(*this, 1)) {
49257330f729Sjoerg AL.setInvalid();
49267330f729Sjoerg return true;
49277330f729Sjoerg }
49287330f729Sjoerg
49297330f729Sjoerg uint32_t NP;
49307330f729Sjoerg Expr *NumParamsExpr = AL.getArgAsExpr(0);
49317330f729Sjoerg if (!checkUInt32Argument(*this, AL, NumParamsExpr, NP)) {
49327330f729Sjoerg AL.setInvalid();
49337330f729Sjoerg return true;
49347330f729Sjoerg }
49357330f729Sjoerg
49367330f729Sjoerg if (Context.getTargetInfo().getRegParmMax() == 0) {
49377330f729Sjoerg Diag(AL.getLoc(), diag::err_attribute_regparm_wrong_platform)
49387330f729Sjoerg << NumParamsExpr->getSourceRange();
49397330f729Sjoerg AL.setInvalid();
49407330f729Sjoerg return true;
49417330f729Sjoerg }
49427330f729Sjoerg
49437330f729Sjoerg numParams = NP;
49447330f729Sjoerg if (numParams > Context.getTargetInfo().getRegParmMax()) {
49457330f729Sjoerg Diag(AL.getLoc(), diag::err_attribute_regparm_invalid_number)
49467330f729Sjoerg << Context.getTargetInfo().getRegParmMax() << NumParamsExpr->getSourceRange();
49477330f729Sjoerg AL.setInvalid();
49487330f729Sjoerg return true;
49497330f729Sjoerg }
49507330f729Sjoerg
49517330f729Sjoerg return false;
49527330f729Sjoerg }
49537330f729Sjoerg
49547330f729Sjoerg // Checks whether an argument of launch_bounds attribute is
49557330f729Sjoerg // acceptable, performs implicit conversion to Rvalue, and returns
49567330f729Sjoerg // non-nullptr Expr result on success. Otherwise, it returns nullptr
49577330f729Sjoerg // and may output an error.
makeLaunchBoundsArgExpr(Sema & S,Expr * E,const CUDALaunchBoundsAttr & AL,const unsigned Idx)49587330f729Sjoerg static Expr *makeLaunchBoundsArgExpr(Sema &S, Expr *E,
49597330f729Sjoerg const CUDALaunchBoundsAttr &AL,
49607330f729Sjoerg const unsigned Idx) {
49617330f729Sjoerg if (S.DiagnoseUnexpandedParameterPack(E))
49627330f729Sjoerg return nullptr;
49637330f729Sjoerg
49647330f729Sjoerg // Accept template arguments for now as they depend on something else.
49657330f729Sjoerg // We'll get to check them when they eventually get instantiated.
49667330f729Sjoerg if (E->isValueDependent())
49677330f729Sjoerg return E;
49687330f729Sjoerg
4969*e038c9c4Sjoerg Optional<llvm::APSInt> I = llvm::APSInt(64);
4970*e038c9c4Sjoerg if (!(I = E->getIntegerConstantExpr(S.Context))) {
49717330f729Sjoerg S.Diag(E->getExprLoc(), diag::err_attribute_argument_n_type)
49727330f729Sjoerg << &AL << Idx << AANT_ArgumentIntegerConstant << E->getSourceRange();
49737330f729Sjoerg return nullptr;
49747330f729Sjoerg }
49757330f729Sjoerg // Make sure we can fit it in 32 bits.
4976*e038c9c4Sjoerg if (!I->isIntN(32)) {
4977*e038c9c4Sjoerg S.Diag(E->getExprLoc(), diag::err_ice_too_large)
4978*e038c9c4Sjoerg << I->toString(10, false) << 32 << /* Unsigned */ 1;
49797330f729Sjoerg return nullptr;
49807330f729Sjoerg }
4981*e038c9c4Sjoerg if (*I < 0)
49827330f729Sjoerg S.Diag(E->getExprLoc(), diag::warn_attribute_argument_n_negative)
49837330f729Sjoerg << &AL << Idx << E->getSourceRange();
49847330f729Sjoerg
49857330f729Sjoerg // We may need to perform implicit conversion of the argument.
49867330f729Sjoerg InitializedEntity Entity = InitializedEntity::InitializeParameter(
49877330f729Sjoerg S.Context, S.Context.getConstType(S.Context.IntTy), /*consume*/ false);
49887330f729Sjoerg ExprResult ValArg = S.PerformCopyInitialization(Entity, SourceLocation(), E);
49897330f729Sjoerg assert(!ValArg.isInvalid() &&
49907330f729Sjoerg "Unexpected PerformCopyInitialization() failure.");
49917330f729Sjoerg
49927330f729Sjoerg return ValArg.getAs<Expr>();
49937330f729Sjoerg }
49947330f729Sjoerg
AddLaunchBoundsAttr(Decl * D,const AttributeCommonInfo & CI,Expr * MaxThreads,Expr * MinBlocks)49957330f729Sjoerg void Sema::AddLaunchBoundsAttr(Decl *D, const AttributeCommonInfo &CI,
49967330f729Sjoerg Expr *MaxThreads, Expr *MinBlocks) {
49977330f729Sjoerg CUDALaunchBoundsAttr TmpAttr(Context, CI, MaxThreads, MinBlocks);
49987330f729Sjoerg MaxThreads = makeLaunchBoundsArgExpr(*this, MaxThreads, TmpAttr, 0);
49997330f729Sjoerg if (MaxThreads == nullptr)
50007330f729Sjoerg return;
50017330f729Sjoerg
50027330f729Sjoerg if (MinBlocks) {
50037330f729Sjoerg MinBlocks = makeLaunchBoundsArgExpr(*this, MinBlocks, TmpAttr, 1);
50047330f729Sjoerg if (MinBlocks == nullptr)
50057330f729Sjoerg return;
50067330f729Sjoerg }
50077330f729Sjoerg
50087330f729Sjoerg D->addAttr(::new (Context)
50097330f729Sjoerg CUDALaunchBoundsAttr(Context, CI, MaxThreads, MinBlocks));
50107330f729Sjoerg }
50117330f729Sjoerg
handleLaunchBoundsAttr(Sema & S,Decl * D,const ParsedAttr & AL)50127330f729Sjoerg static void handleLaunchBoundsAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
5013*e038c9c4Sjoerg if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 2))
50147330f729Sjoerg return;
50157330f729Sjoerg
50167330f729Sjoerg S.AddLaunchBoundsAttr(D, AL, AL.getArgAsExpr(0),
50177330f729Sjoerg AL.getNumArgs() > 1 ? AL.getArgAsExpr(1) : nullptr);
50187330f729Sjoerg }
50197330f729Sjoerg
handleArgumentWithTypeTagAttr(Sema & S,Decl * D,const ParsedAttr & AL)50207330f729Sjoerg static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
50217330f729Sjoerg const ParsedAttr &AL) {
50227330f729Sjoerg if (!AL.isArgIdent(0)) {
50237330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
50247330f729Sjoerg << AL << /* arg num = */ 1 << AANT_ArgumentIdentifier;
50257330f729Sjoerg return;
50267330f729Sjoerg }
50277330f729Sjoerg
50287330f729Sjoerg ParamIdx ArgumentIdx;
50297330f729Sjoerg if (!checkFunctionOrMethodParameterIndex(S, D, AL, 2, AL.getArgAsExpr(1),
50307330f729Sjoerg ArgumentIdx))
50317330f729Sjoerg return;
50327330f729Sjoerg
50337330f729Sjoerg ParamIdx TypeTagIdx;
50347330f729Sjoerg if (!checkFunctionOrMethodParameterIndex(S, D, AL, 3, AL.getArgAsExpr(2),
50357330f729Sjoerg TypeTagIdx))
50367330f729Sjoerg return;
50377330f729Sjoerg
50387330f729Sjoerg bool IsPointer = AL.getAttrName()->getName() == "pointer_with_type_tag";
50397330f729Sjoerg if (IsPointer) {
50407330f729Sjoerg // Ensure that buffer has a pointer type.
50417330f729Sjoerg unsigned ArgumentIdxAST = ArgumentIdx.getASTIndex();
50427330f729Sjoerg if (ArgumentIdxAST >= getFunctionOrMethodNumParams(D) ||
50437330f729Sjoerg !getFunctionOrMethodParamType(D, ArgumentIdxAST)->isPointerType())
50447330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_pointers_only) << AL << 0;
50457330f729Sjoerg }
50467330f729Sjoerg
50477330f729Sjoerg D->addAttr(::new (S.Context) ArgumentWithTypeTagAttr(
50487330f729Sjoerg S.Context, AL, AL.getArgAsIdent(0)->Ident, ArgumentIdx, TypeTagIdx,
50497330f729Sjoerg IsPointer));
50507330f729Sjoerg }
50517330f729Sjoerg
handleTypeTagForDatatypeAttr(Sema & S,Decl * D,const ParsedAttr & AL)50527330f729Sjoerg static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D,
50537330f729Sjoerg const ParsedAttr &AL) {
50547330f729Sjoerg if (!AL.isArgIdent(0)) {
50557330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
50567330f729Sjoerg << AL << 1 << AANT_ArgumentIdentifier;
50577330f729Sjoerg return;
50587330f729Sjoerg }
50597330f729Sjoerg
5060*e038c9c4Sjoerg if (!AL.checkExactlyNumArgs(S, 1))
50617330f729Sjoerg return;
50627330f729Sjoerg
50637330f729Sjoerg if (!isa<VarDecl>(D)) {
50647330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_wrong_decl_type)
50657330f729Sjoerg << AL << ExpectedVariable;
50667330f729Sjoerg return;
50677330f729Sjoerg }
50687330f729Sjoerg
50697330f729Sjoerg IdentifierInfo *PointerKind = AL.getArgAsIdent(0)->Ident;
50707330f729Sjoerg TypeSourceInfo *MatchingCTypeLoc = nullptr;
50717330f729Sjoerg S.GetTypeFromParser(AL.getMatchingCType(), &MatchingCTypeLoc);
50727330f729Sjoerg assert(MatchingCTypeLoc && "no type source info for attribute argument");
50737330f729Sjoerg
50747330f729Sjoerg D->addAttr(::new (S.Context) TypeTagForDatatypeAttr(
50757330f729Sjoerg S.Context, AL, PointerKind, MatchingCTypeLoc, AL.getLayoutCompatible(),
50767330f729Sjoerg AL.getMustBeNull()));
50777330f729Sjoerg }
50787330f729Sjoerg
handleXRayLogArgsAttr(Sema & S,Decl * D,const ParsedAttr & AL)50797330f729Sjoerg static void handleXRayLogArgsAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
50807330f729Sjoerg ParamIdx ArgCount;
50817330f729Sjoerg
50827330f729Sjoerg if (!checkFunctionOrMethodParameterIndex(S, D, AL, 1, AL.getArgAsExpr(0),
50837330f729Sjoerg ArgCount,
50847330f729Sjoerg true /* CanIndexImplicitThis */))
50857330f729Sjoerg return;
50867330f729Sjoerg
50877330f729Sjoerg // ArgCount isn't a parameter index [0;n), it's a count [1;n]
50887330f729Sjoerg D->addAttr(::new (S.Context)
50897330f729Sjoerg XRayLogArgsAttr(S.Context, AL, ArgCount.getSourceIndex()));
50907330f729Sjoerg }
50917330f729Sjoerg
handlePatchableFunctionEntryAttr(Sema & S,Decl * D,const ParsedAttr & AL)5092*e038c9c4Sjoerg static void handlePatchableFunctionEntryAttr(Sema &S, Decl *D,
5093*e038c9c4Sjoerg const ParsedAttr &AL) {
5094*e038c9c4Sjoerg uint32_t Count = 0, Offset = 0;
5095*e038c9c4Sjoerg if (!checkUInt32Argument(S, AL, AL.getArgAsExpr(0), Count, 0, true))
5096*e038c9c4Sjoerg return;
5097*e038c9c4Sjoerg if (AL.getNumArgs() == 2) {
5098*e038c9c4Sjoerg Expr *Arg = AL.getArgAsExpr(1);
5099*e038c9c4Sjoerg if (!checkUInt32Argument(S, AL, Arg, Offset, 1, true))
5100*e038c9c4Sjoerg return;
5101*e038c9c4Sjoerg if (Count < Offset) {
5102*e038c9c4Sjoerg S.Diag(getAttrLoc(AL), diag::err_attribute_argument_out_of_range)
5103*e038c9c4Sjoerg << &AL << 0 << Count << Arg->getBeginLoc();
5104*e038c9c4Sjoerg return;
51057330f729Sjoerg }
51067330f729Sjoerg }
5107*e038c9c4Sjoerg D->addAttr(::new (S.Context)
5108*e038c9c4Sjoerg PatchableFunctionEntryAttr(S.Context, AL, Count, Offset));
5109*e038c9c4Sjoerg }
51107330f729Sjoerg
5111*e038c9c4Sjoerg namespace {
5112*e038c9c4Sjoerg struct IntrinToName {
5113*e038c9c4Sjoerg uint32_t Id;
5114*e038c9c4Sjoerg int32_t FullName;
5115*e038c9c4Sjoerg int32_t ShortName;
5116*e038c9c4Sjoerg };
5117*e038c9c4Sjoerg } // unnamed namespace
5118*e038c9c4Sjoerg
ArmBuiltinAliasValid(unsigned BuiltinID,StringRef AliasName,ArrayRef<IntrinToName> Map,const char * IntrinNames)5119*e038c9c4Sjoerg static bool ArmBuiltinAliasValid(unsigned BuiltinID, StringRef AliasName,
5120*e038c9c4Sjoerg ArrayRef<IntrinToName> Map,
5121*e038c9c4Sjoerg const char *IntrinNames) {
5122*e038c9c4Sjoerg if (AliasName.startswith("__arm_"))
5123*e038c9c4Sjoerg AliasName = AliasName.substr(6);
5124*e038c9c4Sjoerg const IntrinToName *It = std::lower_bound(
5125*e038c9c4Sjoerg Map.begin(), Map.end(), BuiltinID,
5126*e038c9c4Sjoerg [](const IntrinToName &L, unsigned Id) { return L.Id < Id; });
5127*e038c9c4Sjoerg if (It == Map.end() || It->Id != BuiltinID)
5128*e038c9c4Sjoerg return false;
5129*e038c9c4Sjoerg StringRef FullName(&IntrinNames[It->FullName]);
5130*e038c9c4Sjoerg if (AliasName == FullName)
5131*e038c9c4Sjoerg return true;
5132*e038c9c4Sjoerg if (It->ShortName == -1)
5133*e038c9c4Sjoerg return false;
5134*e038c9c4Sjoerg StringRef ShortName(&IntrinNames[It->ShortName]);
5135*e038c9c4Sjoerg return AliasName == ShortName;
5136*e038c9c4Sjoerg }
5137*e038c9c4Sjoerg
ArmMveAliasValid(unsigned BuiltinID,StringRef AliasName)5138*e038c9c4Sjoerg static bool ArmMveAliasValid(unsigned BuiltinID, StringRef AliasName) {
5139*e038c9c4Sjoerg #include "clang/Basic/arm_mve_builtin_aliases.inc"
5140*e038c9c4Sjoerg // The included file defines:
5141*e038c9c4Sjoerg // - ArrayRef<IntrinToName> Map
5142*e038c9c4Sjoerg // - const char IntrinNames[]
5143*e038c9c4Sjoerg return ArmBuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames);
5144*e038c9c4Sjoerg }
5145*e038c9c4Sjoerg
ArmCdeAliasValid(unsigned BuiltinID,StringRef AliasName)5146*e038c9c4Sjoerg static bool ArmCdeAliasValid(unsigned BuiltinID, StringRef AliasName) {
5147*e038c9c4Sjoerg #include "clang/Basic/arm_cde_builtin_aliases.inc"
5148*e038c9c4Sjoerg return ArmBuiltinAliasValid(BuiltinID, AliasName, Map, IntrinNames);
5149*e038c9c4Sjoerg }
5150*e038c9c4Sjoerg
ArmSveAliasValid(unsigned BuiltinID,StringRef AliasName)5151*e038c9c4Sjoerg static bool ArmSveAliasValid(unsigned BuiltinID, StringRef AliasName) {
5152*e038c9c4Sjoerg return BuiltinID >= AArch64::FirstSVEBuiltin &&
5153*e038c9c4Sjoerg BuiltinID <= AArch64::LastSVEBuiltin;
5154*e038c9c4Sjoerg }
5155*e038c9c4Sjoerg
handleArmBuiltinAliasAttr(Sema & S,Decl * D,const ParsedAttr & AL)5156*e038c9c4Sjoerg static void handleArmBuiltinAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
51577330f729Sjoerg if (!AL.isArgIdent(0)) {
51587330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
51597330f729Sjoerg << AL << 1 << AANT_ArgumentIdentifier;
51607330f729Sjoerg return;
51617330f729Sjoerg }
51627330f729Sjoerg
51637330f729Sjoerg IdentifierInfo *Ident = AL.getArgAsIdent(0)->Ident;
51647330f729Sjoerg unsigned BuiltinID = Ident->getBuiltinID();
5165*e038c9c4Sjoerg StringRef AliasName = cast<FunctionDecl>(D)->getIdentifier()->getName();
51667330f729Sjoerg
5167*e038c9c4Sjoerg bool IsAArch64 = S.Context.getTargetInfo().getTriple().isAArch64();
5168*e038c9c4Sjoerg if ((IsAArch64 && !ArmSveAliasValid(BuiltinID, AliasName)) ||
5169*e038c9c4Sjoerg (!IsAArch64 && !ArmMveAliasValid(BuiltinID, AliasName) &&
5170*e038c9c4Sjoerg !ArmCdeAliasValid(BuiltinID, AliasName))) {
5171*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_arm_builtin_alias);
51727330f729Sjoerg return;
51737330f729Sjoerg }
51747330f729Sjoerg
5175*e038c9c4Sjoerg D->addAttr(::new (S.Context) ArmBuiltinAliasAttr(S.Context, AL, Ident));
5176*e038c9c4Sjoerg }
5177*e038c9c4Sjoerg
RISCVAliasValid(unsigned BuiltinID,StringRef AliasName)5178*e038c9c4Sjoerg static bool RISCVAliasValid(unsigned BuiltinID, StringRef AliasName) {
5179*e038c9c4Sjoerg return BuiltinID >= Builtin::FirstTSBuiltin &&
5180*e038c9c4Sjoerg BuiltinID < RISCV::LastTSBuiltin;
5181*e038c9c4Sjoerg }
5182*e038c9c4Sjoerg
handleBuiltinAliasAttr(Sema & S,Decl * D,const ParsedAttr & AL)5183*e038c9c4Sjoerg static void handleBuiltinAliasAttr(Sema &S, Decl *D,
5184*e038c9c4Sjoerg const ParsedAttr &AL) {
5185*e038c9c4Sjoerg if (!AL.isArgIdent(0)) {
5186*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
5187*e038c9c4Sjoerg << AL << 1 << AANT_ArgumentIdentifier;
5188*e038c9c4Sjoerg return;
5189*e038c9c4Sjoerg }
5190*e038c9c4Sjoerg
5191*e038c9c4Sjoerg IdentifierInfo *Ident = AL.getArgAsIdent(0)->Ident;
5192*e038c9c4Sjoerg unsigned BuiltinID = Ident->getBuiltinID();
5193*e038c9c4Sjoerg StringRef AliasName = cast<FunctionDecl>(D)->getIdentifier()->getName();
5194*e038c9c4Sjoerg
5195*e038c9c4Sjoerg bool IsAArch64 = S.Context.getTargetInfo().getTriple().isAArch64();
5196*e038c9c4Sjoerg bool IsARM = S.Context.getTargetInfo().getTriple().isARM();
5197*e038c9c4Sjoerg bool IsRISCV = S.Context.getTargetInfo().getTriple().isRISCV();
5198*e038c9c4Sjoerg if ((IsAArch64 && !ArmSveAliasValid(BuiltinID, AliasName)) ||
5199*e038c9c4Sjoerg (IsARM && !ArmMveAliasValid(BuiltinID, AliasName) &&
5200*e038c9c4Sjoerg !ArmCdeAliasValid(BuiltinID, AliasName)) ||
5201*e038c9c4Sjoerg (IsRISCV && !RISCVAliasValid(BuiltinID, AliasName)) ||
5202*e038c9c4Sjoerg (!IsAArch64 && !IsARM && !IsRISCV)) {
5203*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_builtin_alias) << AL;
5204*e038c9c4Sjoerg return;
5205*e038c9c4Sjoerg }
5206*e038c9c4Sjoerg
5207*e038c9c4Sjoerg D->addAttr(::new (S.Context) BuiltinAliasAttr(S.Context, AL, Ident));
52087330f729Sjoerg }
52097330f729Sjoerg
52107330f729Sjoerg //===----------------------------------------------------------------------===//
52117330f729Sjoerg // Checker-specific attribute handlers.
52127330f729Sjoerg //===----------------------------------------------------------------------===//
isValidSubjectOfNSReturnsRetainedAttribute(QualType QT)52137330f729Sjoerg static bool isValidSubjectOfNSReturnsRetainedAttribute(QualType QT) {
52147330f729Sjoerg return QT->isDependentType() || QT->isObjCRetainableType();
52157330f729Sjoerg }
52167330f729Sjoerg
isValidSubjectOfNSAttribute(QualType QT)52177330f729Sjoerg static bool isValidSubjectOfNSAttribute(QualType QT) {
52187330f729Sjoerg return QT->isDependentType() || QT->isObjCObjectPointerType() ||
52197330f729Sjoerg QT->isObjCNSObjectType();
52207330f729Sjoerg }
52217330f729Sjoerg
isValidSubjectOfCFAttribute(QualType QT)52227330f729Sjoerg static bool isValidSubjectOfCFAttribute(QualType QT) {
52237330f729Sjoerg return QT->isDependentType() || QT->isPointerType() ||
52247330f729Sjoerg isValidSubjectOfNSAttribute(QT);
52257330f729Sjoerg }
52267330f729Sjoerg
isValidSubjectOfOSAttribute(QualType QT)52277330f729Sjoerg static bool isValidSubjectOfOSAttribute(QualType QT) {
52287330f729Sjoerg if (QT->isDependentType())
52297330f729Sjoerg return true;
52307330f729Sjoerg QualType PT = QT->getPointeeType();
52317330f729Sjoerg return !PT.isNull() && PT->getAsCXXRecordDecl() != nullptr;
52327330f729Sjoerg }
52337330f729Sjoerg
AddXConsumedAttr(Decl * D,const AttributeCommonInfo & CI,RetainOwnershipKind K,bool IsTemplateInstantiation)52347330f729Sjoerg void Sema::AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI,
52357330f729Sjoerg RetainOwnershipKind K,
52367330f729Sjoerg bool IsTemplateInstantiation) {
52377330f729Sjoerg ValueDecl *VD = cast<ValueDecl>(D);
52387330f729Sjoerg switch (K) {
52397330f729Sjoerg case RetainOwnershipKind::OS:
52407330f729Sjoerg handleSimpleAttributeOrDiagnose<OSConsumedAttr>(
52417330f729Sjoerg *this, VD, CI, isValidSubjectOfOSAttribute(VD->getType()),
52427330f729Sjoerg diag::warn_ns_attribute_wrong_parameter_type,
52437330f729Sjoerg /*ExtraArgs=*/CI.getRange(), "os_consumed", /*pointers*/ 1);
52447330f729Sjoerg return;
52457330f729Sjoerg case RetainOwnershipKind::NS:
52467330f729Sjoerg handleSimpleAttributeOrDiagnose<NSConsumedAttr>(
52477330f729Sjoerg *this, VD, CI, isValidSubjectOfNSAttribute(VD->getType()),
52487330f729Sjoerg
52497330f729Sjoerg // These attributes are normally just advisory, but in ARC, ns_consumed
52507330f729Sjoerg // is significant. Allow non-dependent code to contain inappropriate
52517330f729Sjoerg // attributes even in ARC, but require template instantiations to be
52527330f729Sjoerg // set up correctly.
52537330f729Sjoerg ((IsTemplateInstantiation && getLangOpts().ObjCAutoRefCount)
52547330f729Sjoerg ? diag::err_ns_attribute_wrong_parameter_type
52557330f729Sjoerg : diag::warn_ns_attribute_wrong_parameter_type),
52567330f729Sjoerg /*ExtraArgs=*/CI.getRange(), "ns_consumed", /*objc pointers*/ 0);
52577330f729Sjoerg return;
52587330f729Sjoerg case RetainOwnershipKind::CF:
52597330f729Sjoerg handleSimpleAttributeOrDiagnose<CFConsumedAttr>(
52607330f729Sjoerg *this, VD, CI, isValidSubjectOfCFAttribute(VD->getType()),
52617330f729Sjoerg diag::warn_ns_attribute_wrong_parameter_type,
52627330f729Sjoerg /*ExtraArgs=*/CI.getRange(), "cf_consumed", /*pointers*/ 1);
52637330f729Sjoerg return;
52647330f729Sjoerg }
52657330f729Sjoerg }
52667330f729Sjoerg
52677330f729Sjoerg static Sema::RetainOwnershipKind
parsedAttrToRetainOwnershipKind(const ParsedAttr & AL)52687330f729Sjoerg parsedAttrToRetainOwnershipKind(const ParsedAttr &AL) {
52697330f729Sjoerg switch (AL.getKind()) {
52707330f729Sjoerg case ParsedAttr::AT_CFConsumed:
52717330f729Sjoerg case ParsedAttr::AT_CFReturnsRetained:
52727330f729Sjoerg case ParsedAttr::AT_CFReturnsNotRetained:
52737330f729Sjoerg return Sema::RetainOwnershipKind::CF;
52747330f729Sjoerg case ParsedAttr::AT_OSConsumesThis:
52757330f729Sjoerg case ParsedAttr::AT_OSConsumed:
52767330f729Sjoerg case ParsedAttr::AT_OSReturnsRetained:
52777330f729Sjoerg case ParsedAttr::AT_OSReturnsNotRetained:
52787330f729Sjoerg case ParsedAttr::AT_OSReturnsRetainedOnZero:
52797330f729Sjoerg case ParsedAttr::AT_OSReturnsRetainedOnNonZero:
52807330f729Sjoerg return Sema::RetainOwnershipKind::OS;
52817330f729Sjoerg case ParsedAttr::AT_NSConsumesSelf:
52827330f729Sjoerg case ParsedAttr::AT_NSConsumed:
52837330f729Sjoerg case ParsedAttr::AT_NSReturnsRetained:
52847330f729Sjoerg case ParsedAttr::AT_NSReturnsNotRetained:
52857330f729Sjoerg case ParsedAttr::AT_NSReturnsAutoreleased:
52867330f729Sjoerg return Sema::RetainOwnershipKind::NS;
52877330f729Sjoerg default:
52887330f729Sjoerg llvm_unreachable("Wrong argument supplied");
52897330f729Sjoerg }
52907330f729Sjoerg }
52917330f729Sjoerg
checkNSReturnsRetainedReturnType(SourceLocation Loc,QualType QT)52927330f729Sjoerg bool Sema::checkNSReturnsRetainedReturnType(SourceLocation Loc, QualType QT) {
52937330f729Sjoerg if (isValidSubjectOfNSReturnsRetainedAttribute(QT))
52947330f729Sjoerg return false;
52957330f729Sjoerg
52967330f729Sjoerg Diag(Loc, diag::warn_ns_attribute_wrong_return_type)
52977330f729Sjoerg << "'ns_returns_retained'" << 0 << 0;
52987330f729Sjoerg return true;
52997330f729Sjoerg }
53007330f729Sjoerg
53017330f729Sjoerg /// \return whether the parameter is a pointer to OSObject pointer.
isValidOSObjectOutParameter(const Decl * D)53027330f729Sjoerg static bool isValidOSObjectOutParameter(const Decl *D) {
53037330f729Sjoerg const auto *PVD = dyn_cast<ParmVarDecl>(D);
53047330f729Sjoerg if (!PVD)
53057330f729Sjoerg return false;
53067330f729Sjoerg QualType QT = PVD->getType();
53077330f729Sjoerg QualType PT = QT->getPointeeType();
53087330f729Sjoerg return !PT.isNull() && isValidSubjectOfOSAttribute(PT);
53097330f729Sjoerg }
53107330f729Sjoerg
handleXReturnsXRetainedAttr(Sema & S,Decl * D,const ParsedAttr & AL)53117330f729Sjoerg static void handleXReturnsXRetainedAttr(Sema &S, Decl *D,
53127330f729Sjoerg const ParsedAttr &AL) {
53137330f729Sjoerg QualType ReturnType;
53147330f729Sjoerg Sema::RetainOwnershipKind K = parsedAttrToRetainOwnershipKind(AL);
53157330f729Sjoerg
53167330f729Sjoerg if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
53177330f729Sjoerg ReturnType = MD->getReturnType();
53187330f729Sjoerg } else if (S.getLangOpts().ObjCAutoRefCount && hasDeclarator(D) &&
53197330f729Sjoerg (AL.getKind() == ParsedAttr::AT_NSReturnsRetained)) {
53207330f729Sjoerg return; // ignore: was handled as a type attribute
53217330f729Sjoerg } else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(D)) {
53227330f729Sjoerg ReturnType = PD->getType();
53237330f729Sjoerg } else if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
53247330f729Sjoerg ReturnType = FD->getReturnType();
53257330f729Sjoerg } else if (const auto *Param = dyn_cast<ParmVarDecl>(D)) {
53267330f729Sjoerg // Attributes on parameters are used for out-parameters,
53277330f729Sjoerg // passed as pointers-to-pointers.
53287330f729Sjoerg unsigned DiagID = K == Sema::RetainOwnershipKind::CF
53297330f729Sjoerg ? /*pointer-to-CF-pointer*/2
53307330f729Sjoerg : /*pointer-to-OSObject-pointer*/3;
53317330f729Sjoerg ReturnType = Param->getType()->getPointeeType();
53327330f729Sjoerg if (ReturnType.isNull()) {
53337330f729Sjoerg S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_parameter_type)
53347330f729Sjoerg << AL << DiagID << AL.getRange();
53357330f729Sjoerg return;
53367330f729Sjoerg }
53377330f729Sjoerg } else if (AL.isUsedAsTypeAttr()) {
53387330f729Sjoerg return;
53397330f729Sjoerg } else {
53407330f729Sjoerg AttributeDeclKind ExpectedDeclKind;
53417330f729Sjoerg switch (AL.getKind()) {
53427330f729Sjoerg default: llvm_unreachable("invalid ownership attribute");
53437330f729Sjoerg case ParsedAttr::AT_NSReturnsRetained:
53447330f729Sjoerg case ParsedAttr::AT_NSReturnsAutoreleased:
53457330f729Sjoerg case ParsedAttr::AT_NSReturnsNotRetained:
53467330f729Sjoerg ExpectedDeclKind = ExpectedFunctionOrMethod;
53477330f729Sjoerg break;
53487330f729Sjoerg
53497330f729Sjoerg case ParsedAttr::AT_OSReturnsRetained:
53507330f729Sjoerg case ParsedAttr::AT_OSReturnsNotRetained:
53517330f729Sjoerg case ParsedAttr::AT_CFReturnsRetained:
53527330f729Sjoerg case ParsedAttr::AT_CFReturnsNotRetained:
53537330f729Sjoerg ExpectedDeclKind = ExpectedFunctionMethodOrParameter;
53547330f729Sjoerg break;
53557330f729Sjoerg }
53567330f729Sjoerg S.Diag(D->getBeginLoc(), diag::warn_attribute_wrong_decl_type)
53577330f729Sjoerg << AL.getRange() << AL << ExpectedDeclKind;
53587330f729Sjoerg return;
53597330f729Sjoerg }
53607330f729Sjoerg
53617330f729Sjoerg bool TypeOK;
53627330f729Sjoerg bool Cf;
53637330f729Sjoerg unsigned ParmDiagID = 2; // Pointer-to-CF-pointer
53647330f729Sjoerg switch (AL.getKind()) {
53657330f729Sjoerg default: llvm_unreachable("invalid ownership attribute");
53667330f729Sjoerg case ParsedAttr::AT_NSReturnsRetained:
53677330f729Sjoerg TypeOK = isValidSubjectOfNSReturnsRetainedAttribute(ReturnType);
53687330f729Sjoerg Cf = false;
53697330f729Sjoerg break;
53707330f729Sjoerg
53717330f729Sjoerg case ParsedAttr::AT_NSReturnsAutoreleased:
53727330f729Sjoerg case ParsedAttr::AT_NSReturnsNotRetained:
53737330f729Sjoerg TypeOK = isValidSubjectOfNSAttribute(ReturnType);
53747330f729Sjoerg Cf = false;
53757330f729Sjoerg break;
53767330f729Sjoerg
53777330f729Sjoerg case ParsedAttr::AT_CFReturnsRetained:
53787330f729Sjoerg case ParsedAttr::AT_CFReturnsNotRetained:
53797330f729Sjoerg TypeOK = isValidSubjectOfCFAttribute(ReturnType);
53807330f729Sjoerg Cf = true;
53817330f729Sjoerg break;
53827330f729Sjoerg
53837330f729Sjoerg case ParsedAttr::AT_OSReturnsRetained:
53847330f729Sjoerg case ParsedAttr::AT_OSReturnsNotRetained:
53857330f729Sjoerg TypeOK = isValidSubjectOfOSAttribute(ReturnType);
53867330f729Sjoerg Cf = true;
53877330f729Sjoerg ParmDiagID = 3; // Pointer-to-OSObject-pointer
53887330f729Sjoerg break;
53897330f729Sjoerg }
53907330f729Sjoerg
53917330f729Sjoerg if (!TypeOK) {
53927330f729Sjoerg if (AL.isUsedAsTypeAttr())
53937330f729Sjoerg return;
53947330f729Sjoerg
53957330f729Sjoerg if (isa<ParmVarDecl>(D)) {
53967330f729Sjoerg S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_parameter_type)
53977330f729Sjoerg << AL << ParmDiagID << AL.getRange();
53987330f729Sjoerg } else {
53997330f729Sjoerg // Needs to be kept in sync with warn_ns_attribute_wrong_return_type.
54007330f729Sjoerg enum : unsigned {
54017330f729Sjoerg Function,
54027330f729Sjoerg Method,
54037330f729Sjoerg Property
54047330f729Sjoerg } SubjectKind = Function;
54057330f729Sjoerg if (isa<ObjCMethodDecl>(D))
54067330f729Sjoerg SubjectKind = Method;
54077330f729Sjoerg else if (isa<ObjCPropertyDecl>(D))
54087330f729Sjoerg SubjectKind = Property;
54097330f729Sjoerg S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_return_type)
54107330f729Sjoerg << AL << SubjectKind << Cf << AL.getRange();
54117330f729Sjoerg }
54127330f729Sjoerg return;
54137330f729Sjoerg }
54147330f729Sjoerg
54157330f729Sjoerg switch (AL.getKind()) {
54167330f729Sjoerg default:
54177330f729Sjoerg llvm_unreachable("invalid ownership attribute");
54187330f729Sjoerg case ParsedAttr::AT_NSReturnsAutoreleased:
54197330f729Sjoerg handleSimpleAttribute<NSReturnsAutoreleasedAttr>(S, D, AL);
54207330f729Sjoerg return;
54217330f729Sjoerg case ParsedAttr::AT_CFReturnsNotRetained:
54227330f729Sjoerg handleSimpleAttribute<CFReturnsNotRetainedAttr>(S, D, AL);
54237330f729Sjoerg return;
54247330f729Sjoerg case ParsedAttr::AT_NSReturnsNotRetained:
54257330f729Sjoerg handleSimpleAttribute<NSReturnsNotRetainedAttr>(S, D, AL);
54267330f729Sjoerg return;
54277330f729Sjoerg case ParsedAttr::AT_CFReturnsRetained:
54287330f729Sjoerg handleSimpleAttribute<CFReturnsRetainedAttr>(S, D, AL);
54297330f729Sjoerg return;
54307330f729Sjoerg case ParsedAttr::AT_NSReturnsRetained:
54317330f729Sjoerg handleSimpleAttribute<NSReturnsRetainedAttr>(S, D, AL);
54327330f729Sjoerg return;
54337330f729Sjoerg case ParsedAttr::AT_OSReturnsRetained:
54347330f729Sjoerg handleSimpleAttribute<OSReturnsRetainedAttr>(S, D, AL);
54357330f729Sjoerg return;
54367330f729Sjoerg case ParsedAttr::AT_OSReturnsNotRetained:
54377330f729Sjoerg handleSimpleAttribute<OSReturnsNotRetainedAttr>(S, D, AL);
54387330f729Sjoerg return;
54397330f729Sjoerg };
54407330f729Sjoerg }
54417330f729Sjoerg
handleObjCReturnsInnerPointerAttr(Sema & S,Decl * D,const ParsedAttr & Attrs)54427330f729Sjoerg static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D,
54437330f729Sjoerg const ParsedAttr &Attrs) {
54447330f729Sjoerg const int EP_ObjCMethod = 1;
54457330f729Sjoerg const int EP_ObjCProperty = 2;
54467330f729Sjoerg
54477330f729Sjoerg SourceLocation loc = Attrs.getLoc();
54487330f729Sjoerg QualType resultType;
54497330f729Sjoerg if (isa<ObjCMethodDecl>(D))
54507330f729Sjoerg resultType = cast<ObjCMethodDecl>(D)->getReturnType();
54517330f729Sjoerg else
54527330f729Sjoerg resultType = cast<ObjCPropertyDecl>(D)->getType();
54537330f729Sjoerg
54547330f729Sjoerg if (!resultType->isReferenceType() &&
54557330f729Sjoerg (!resultType->isPointerType() || resultType->isObjCRetainableType())) {
54567330f729Sjoerg S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_return_type)
54577330f729Sjoerg << SourceRange(loc) << Attrs
54587330f729Sjoerg << (isa<ObjCMethodDecl>(D) ? EP_ObjCMethod : EP_ObjCProperty)
54597330f729Sjoerg << /*non-retainable pointer*/ 2;
54607330f729Sjoerg
54617330f729Sjoerg // Drop the attribute.
54627330f729Sjoerg return;
54637330f729Sjoerg }
54647330f729Sjoerg
54657330f729Sjoerg D->addAttr(::new (S.Context) ObjCReturnsInnerPointerAttr(S.Context, Attrs));
54667330f729Sjoerg }
54677330f729Sjoerg
handleObjCRequiresSuperAttr(Sema & S,Decl * D,const ParsedAttr & Attrs)54687330f729Sjoerg static void handleObjCRequiresSuperAttr(Sema &S, Decl *D,
54697330f729Sjoerg const ParsedAttr &Attrs) {
54707330f729Sjoerg const auto *Method = cast<ObjCMethodDecl>(D);
54717330f729Sjoerg
54727330f729Sjoerg const DeclContext *DC = Method->getDeclContext();
54737330f729Sjoerg if (const auto *PDecl = dyn_cast_or_null<ObjCProtocolDecl>(DC)) {
54747330f729Sjoerg S.Diag(D->getBeginLoc(), diag::warn_objc_requires_super_protocol) << Attrs
54757330f729Sjoerg << 0;
54767330f729Sjoerg S.Diag(PDecl->getLocation(), diag::note_protocol_decl);
54777330f729Sjoerg return;
54787330f729Sjoerg }
54797330f729Sjoerg if (Method->getMethodFamily() == OMF_dealloc) {
54807330f729Sjoerg S.Diag(D->getBeginLoc(), diag::warn_objc_requires_super_protocol) << Attrs
54817330f729Sjoerg << 1;
54827330f729Sjoerg return;
54837330f729Sjoerg }
54847330f729Sjoerg
54857330f729Sjoerg D->addAttr(::new (S.Context) ObjCRequiresSuperAttr(S.Context, Attrs));
54867330f729Sjoerg }
54877330f729Sjoerg
handleNSErrorDomain(Sema & S,Decl * D,const ParsedAttr & AL)5488*e038c9c4Sjoerg static void handleNSErrorDomain(Sema &S, Decl *D, const ParsedAttr &AL) {
5489*e038c9c4Sjoerg auto *E = AL.getArgAsExpr(0);
5490*e038c9c4Sjoerg auto Loc = E ? E->getBeginLoc() : AL.getLoc();
5491*e038c9c4Sjoerg
5492*e038c9c4Sjoerg auto *DRE = dyn_cast<DeclRefExpr>(AL.getArgAsExpr(0));
5493*e038c9c4Sjoerg if (!DRE) {
5494*e038c9c4Sjoerg S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 0;
5495*e038c9c4Sjoerg return;
5496*e038c9c4Sjoerg }
5497*e038c9c4Sjoerg
5498*e038c9c4Sjoerg auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
5499*e038c9c4Sjoerg if (!VD) {
5500*e038c9c4Sjoerg S.Diag(Loc, diag::err_nserrordomain_invalid_decl) << 1 << DRE->getDecl();
5501*e038c9c4Sjoerg return;
5502*e038c9c4Sjoerg }
5503*e038c9c4Sjoerg
5504*e038c9c4Sjoerg if (!isNSStringType(VD->getType(), S.Context) &&
5505*e038c9c4Sjoerg !isCFStringType(VD->getType(), S.Context)) {
5506*e038c9c4Sjoerg S.Diag(Loc, diag::err_nserrordomain_wrong_type) << VD;
5507*e038c9c4Sjoerg return;
5508*e038c9c4Sjoerg }
5509*e038c9c4Sjoerg
5510*e038c9c4Sjoerg D->addAttr(::new (S.Context) NSErrorDomainAttr(S.Context, AL, VD));
5511*e038c9c4Sjoerg }
5512*e038c9c4Sjoerg
handleObjCBridgeAttr(Sema & S,Decl * D,const ParsedAttr & AL)55137330f729Sjoerg static void handleObjCBridgeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
55147330f729Sjoerg IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr;
55157330f729Sjoerg
55167330f729Sjoerg if (!Parm) {
55177330f729Sjoerg S.Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0;
55187330f729Sjoerg return;
55197330f729Sjoerg }
55207330f729Sjoerg
55217330f729Sjoerg // Typedefs only allow objc_bridge(id) and have some additional checking.
55227330f729Sjoerg if (const auto *TD = dyn_cast<TypedefNameDecl>(D)) {
55237330f729Sjoerg if (!Parm->Ident->isStr("id")) {
55247330f729Sjoerg S.Diag(AL.getLoc(), diag::err_objc_attr_typedef_not_id) << AL;
55257330f729Sjoerg return;
55267330f729Sjoerg }
55277330f729Sjoerg
55287330f729Sjoerg // Only allow 'cv void *'.
55297330f729Sjoerg QualType T = TD->getUnderlyingType();
55307330f729Sjoerg if (!T->isVoidPointerType()) {
55317330f729Sjoerg S.Diag(AL.getLoc(), diag::err_objc_attr_typedef_not_void_pointer);
55327330f729Sjoerg return;
55337330f729Sjoerg }
55347330f729Sjoerg }
55357330f729Sjoerg
55367330f729Sjoerg D->addAttr(::new (S.Context) ObjCBridgeAttr(S.Context, AL, Parm->Ident));
55377330f729Sjoerg }
55387330f729Sjoerg
handleObjCBridgeMutableAttr(Sema & S,Decl * D,const ParsedAttr & AL)55397330f729Sjoerg static void handleObjCBridgeMutableAttr(Sema &S, Decl *D,
55407330f729Sjoerg const ParsedAttr &AL) {
55417330f729Sjoerg IdentifierLoc *Parm = AL.isArgIdent(0) ? AL.getArgAsIdent(0) : nullptr;
55427330f729Sjoerg
55437330f729Sjoerg if (!Parm) {
55447330f729Sjoerg S.Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0;
55457330f729Sjoerg return;
55467330f729Sjoerg }
55477330f729Sjoerg
55487330f729Sjoerg D->addAttr(::new (S.Context)
55497330f729Sjoerg ObjCBridgeMutableAttr(S.Context, AL, Parm->Ident));
55507330f729Sjoerg }
55517330f729Sjoerg
handleObjCBridgeRelatedAttr(Sema & S,Decl * D,const ParsedAttr & AL)55527330f729Sjoerg static void handleObjCBridgeRelatedAttr(Sema &S, Decl *D,
55537330f729Sjoerg const ParsedAttr &AL) {
55547330f729Sjoerg IdentifierInfo *RelatedClass =
55557330f729Sjoerg AL.isArgIdent(0) ? AL.getArgAsIdent(0)->Ident : nullptr;
55567330f729Sjoerg if (!RelatedClass) {
55577330f729Sjoerg S.Diag(D->getBeginLoc(), diag::err_objc_attr_not_id) << AL << 0;
55587330f729Sjoerg return;
55597330f729Sjoerg }
55607330f729Sjoerg IdentifierInfo *ClassMethod =
55617330f729Sjoerg AL.getArgAsIdent(1) ? AL.getArgAsIdent(1)->Ident : nullptr;
55627330f729Sjoerg IdentifierInfo *InstanceMethod =
55637330f729Sjoerg AL.getArgAsIdent(2) ? AL.getArgAsIdent(2)->Ident : nullptr;
55647330f729Sjoerg D->addAttr(::new (S.Context) ObjCBridgeRelatedAttr(
55657330f729Sjoerg S.Context, AL, RelatedClass, ClassMethod, InstanceMethod));
55667330f729Sjoerg }
55677330f729Sjoerg
handleObjCDesignatedInitializer(Sema & S,Decl * D,const ParsedAttr & AL)55687330f729Sjoerg static void handleObjCDesignatedInitializer(Sema &S, Decl *D,
55697330f729Sjoerg const ParsedAttr &AL) {
55707330f729Sjoerg DeclContext *Ctx = D->getDeclContext();
55717330f729Sjoerg
55727330f729Sjoerg // This attribute can only be applied to methods in interfaces or class
55737330f729Sjoerg // extensions.
55747330f729Sjoerg if (!isa<ObjCInterfaceDecl>(Ctx) &&
55757330f729Sjoerg !(isa<ObjCCategoryDecl>(Ctx) &&
55767330f729Sjoerg cast<ObjCCategoryDecl>(Ctx)->IsClassExtension())) {
55777330f729Sjoerg S.Diag(D->getLocation(), diag::err_designated_init_attr_non_init);
55787330f729Sjoerg return;
55797330f729Sjoerg }
55807330f729Sjoerg
55817330f729Sjoerg ObjCInterfaceDecl *IFace;
55827330f729Sjoerg if (auto *CatDecl = dyn_cast<ObjCCategoryDecl>(Ctx))
55837330f729Sjoerg IFace = CatDecl->getClassInterface();
55847330f729Sjoerg else
55857330f729Sjoerg IFace = cast<ObjCInterfaceDecl>(Ctx);
55867330f729Sjoerg
55877330f729Sjoerg if (!IFace)
55887330f729Sjoerg return;
55897330f729Sjoerg
55907330f729Sjoerg IFace->setHasDesignatedInitializers();
55917330f729Sjoerg D->addAttr(::new (S.Context) ObjCDesignatedInitializerAttr(S.Context, AL));
55927330f729Sjoerg }
55937330f729Sjoerg
handleObjCRuntimeName(Sema & S,Decl * D,const ParsedAttr & AL)55947330f729Sjoerg static void handleObjCRuntimeName(Sema &S, Decl *D, const ParsedAttr &AL) {
55957330f729Sjoerg StringRef MetaDataName;
55967330f729Sjoerg if (!S.checkStringLiteralArgumentAttr(AL, 0, MetaDataName))
55977330f729Sjoerg return;
55987330f729Sjoerg D->addAttr(::new (S.Context)
55997330f729Sjoerg ObjCRuntimeNameAttr(S.Context, AL, MetaDataName));
56007330f729Sjoerg }
56017330f729Sjoerg
56027330f729Sjoerg // When a user wants to use objc_boxable with a union or struct
56037330f729Sjoerg // but they don't have access to the declaration (legacy/third-party code)
56047330f729Sjoerg // then they can 'enable' this feature with a typedef:
56057330f729Sjoerg // typedef struct __attribute((objc_boxable)) legacy_struct legacy_struct;
handleObjCBoxable(Sema & S,Decl * D,const ParsedAttr & AL)56067330f729Sjoerg static void handleObjCBoxable(Sema &S, Decl *D, const ParsedAttr &AL) {
56077330f729Sjoerg bool notify = false;
56087330f729Sjoerg
56097330f729Sjoerg auto *RD = dyn_cast<RecordDecl>(D);
56107330f729Sjoerg if (RD && RD->getDefinition()) {
56117330f729Sjoerg RD = RD->getDefinition();
56127330f729Sjoerg notify = true;
56137330f729Sjoerg }
56147330f729Sjoerg
56157330f729Sjoerg if (RD) {
56167330f729Sjoerg ObjCBoxableAttr *BoxableAttr =
56177330f729Sjoerg ::new (S.Context) ObjCBoxableAttr(S.Context, AL);
56187330f729Sjoerg RD->addAttr(BoxableAttr);
56197330f729Sjoerg if (notify) {
56207330f729Sjoerg // we need to notify ASTReader/ASTWriter about
56217330f729Sjoerg // modification of existing declaration
56227330f729Sjoerg if (ASTMutationListener *L = S.getASTMutationListener())
56237330f729Sjoerg L->AddedAttributeToRecord(BoxableAttr, RD);
56247330f729Sjoerg }
56257330f729Sjoerg }
56267330f729Sjoerg }
56277330f729Sjoerg
handleObjCOwnershipAttr(Sema & S,Decl * D,const ParsedAttr & AL)56287330f729Sjoerg static void handleObjCOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
56297330f729Sjoerg if (hasDeclarator(D)) return;
56307330f729Sjoerg
56317330f729Sjoerg S.Diag(D->getBeginLoc(), diag::err_attribute_wrong_decl_type)
56327330f729Sjoerg << AL.getRange() << AL << ExpectedVariable;
56337330f729Sjoerg }
56347330f729Sjoerg
handleObjCPreciseLifetimeAttr(Sema & S,Decl * D,const ParsedAttr & AL)56357330f729Sjoerg static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D,
56367330f729Sjoerg const ParsedAttr &AL) {
56377330f729Sjoerg const auto *VD = cast<ValueDecl>(D);
56387330f729Sjoerg QualType QT = VD->getType();
56397330f729Sjoerg
56407330f729Sjoerg if (!QT->isDependentType() &&
56417330f729Sjoerg !QT->isObjCLifetimeType()) {
56427330f729Sjoerg S.Diag(AL.getLoc(), diag::err_objc_precise_lifetime_bad_type)
56437330f729Sjoerg << QT;
56447330f729Sjoerg return;
56457330f729Sjoerg }
56467330f729Sjoerg
56477330f729Sjoerg Qualifiers::ObjCLifetime Lifetime = QT.getObjCLifetime();
56487330f729Sjoerg
56497330f729Sjoerg // If we have no lifetime yet, check the lifetime we're presumably
56507330f729Sjoerg // going to infer.
56517330f729Sjoerg if (Lifetime == Qualifiers::OCL_None && !QT->isDependentType())
56527330f729Sjoerg Lifetime = QT->getObjCARCImplicitLifetime();
56537330f729Sjoerg
56547330f729Sjoerg switch (Lifetime) {
56557330f729Sjoerg case Qualifiers::OCL_None:
56567330f729Sjoerg assert(QT->isDependentType() &&
56577330f729Sjoerg "didn't infer lifetime for non-dependent type?");
56587330f729Sjoerg break;
56597330f729Sjoerg
56607330f729Sjoerg case Qualifiers::OCL_Weak: // meaningful
56617330f729Sjoerg case Qualifiers::OCL_Strong: // meaningful
56627330f729Sjoerg break;
56637330f729Sjoerg
56647330f729Sjoerg case Qualifiers::OCL_ExplicitNone:
56657330f729Sjoerg case Qualifiers::OCL_Autoreleasing:
56667330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_objc_precise_lifetime_meaningless)
56677330f729Sjoerg << (Lifetime == Qualifiers::OCL_Autoreleasing);
56687330f729Sjoerg break;
56697330f729Sjoerg }
56707330f729Sjoerg
56717330f729Sjoerg D->addAttr(::new (S.Context) ObjCPreciseLifetimeAttr(S.Context, AL));
56727330f729Sjoerg }
56737330f729Sjoerg
handleSwiftAttrAttr(Sema & S,Decl * D,const ParsedAttr & AL)5674*e038c9c4Sjoerg static void handleSwiftAttrAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
5675*e038c9c4Sjoerg // Make sure that there is a string literal as the annotation's single
5676*e038c9c4Sjoerg // argument.
5677*e038c9c4Sjoerg StringRef Str;
5678*e038c9c4Sjoerg if (!S.checkStringLiteralArgumentAttr(AL, 0, Str))
5679*e038c9c4Sjoerg return;
5680*e038c9c4Sjoerg
5681*e038c9c4Sjoerg D->addAttr(::new (S.Context) SwiftAttrAttr(S.Context, AL, Str));
5682*e038c9c4Sjoerg }
5683*e038c9c4Sjoerg
handleSwiftBridge(Sema & S,Decl * D,const ParsedAttr & AL)5684*e038c9c4Sjoerg static void handleSwiftBridge(Sema &S, Decl *D, const ParsedAttr &AL) {
5685*e038c9c4Sjoerg // Make sure that there is a string literal as the annotation's single
5686*e038c9c4Sjoerg // argument.
5687*e038c9c4Sjoerg StringRef BT;
5688*e038c9c4Sjoerg if (!S.checkStringLiteralArgumentAttr(AL, 0, BT))
5689*e038c9c4Sjoerg return;
5690*e038c9c4Sjoerg
5691*e038c9c4Sjoerg // Warn about duplicate attributes if they have different arguments, but drop
5692*e038c9c4Sjoerg // any duplicate attributes regardless.
5693*e038c9c4Sjoerg if (const auto *Other = D->getAttr<SwiftBridgeAttr>()) {
5694*e038c9c4Sjoerg if (Other->getSwiftType() != BT)
5695*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
5696*e038c9c4Sjoerg return;
5697*e038c9c4Sjoerg }
5698*e038c9c4Sjoerg
5699*e038c9c4Sjoerg D->addAttr(::new (S.Context) SwiftBridgeAttr(S.Context, AL, BT));
5700*e038c9c4Sjoerg }
5701*e038c9c4Sjoerg
isErrorParameter(Sema & S,QualType QT)5702*e038c9c4Sjoerg static bool isErrorParameter(Sema &S, QualType QT) {
5703*e038c9c4Sjoerg const auto *PT = QT->getAs<PointerType>();
5704*e038c9c4Sjoerg if (!PT)
5705*e038c9c4Sjoerg return false;
5706*e038c9c4Sjoerg
5707*e038c9c4Sjoerg QualType Pointee = PT->getPointeeType();
5708*e038c9c4Sjoerg
5709*e038c9c4Sjoerg // Check for NSError**.
5710*e038c9c4Sjoerg if (const auto *OPT = Pointee->getAs<ObjCObjectPointerType>())
5711*e038c9c4Sjoerg if (const auto *ID = OPT->getInterfaceDecl())
5712*e038c9c4Sjoerg if (ID->getIdentifier() == S.getNSErrorIdent())
5713*e038c9c4Sjoerg return true;
5714*e038c9c4Sjoerg
5715*e038c9c4Sjoerg // Check for CFError**.
5716*e038c9c4Sjoerg if (const auto *PT = Pointee->getAs<PointerType>())
5717*e038c9c4Sjoerg if (const auto *RT = PT->getPointeeType()->getAs<RecordType>())
5718*e038c9c4Sjoerg if (S.isCFError(RT->getDecl()))
5719*e038c9c4Sjoerg return true;
5720*e038c9c4Sjoerg
5721*e038c9c4Sjoerg return false;
5722*e038c9c4Sjoerg }
5723*e038c9c4Sjoerg
handleSwiftError(Sema & S,Decl * D,const ParsedAttr & AL)5724*e038c9c4Sjoerg static void handleSwiftError(Sema &S, Decl *D, const ParsedAttr &AL) {
5725*e038c9c4Sjoerg auto hasErrorParameter = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {
5726*e038c9c4Sjoerg for (unsigned I = 0, E = getFunctionOrMethodNumParams(D); I != E; ++I) {
5727*e038c9c4Sjoerg if (isErrorParameter(S, getFunctionOrMethodParamType(D, I)))
5728*e038c9c4Sjoerg return true;
5729*e038c9c4Sjoerg }
5730*e038c9c4Sjoerg
5731*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::err_attr_swift_error_no_error_parameter)
5732*e038c9c4Sjoerg << AL << isa<ObjCMethodDecl>(D);
5733*e038c9c4Sjoerg return false;
5734*e038c9c4Sjoerg };
5735*e038c9c4Sjoerg
5736*e038c9c4Sjoerg auto hasPointerResult = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {
5737*e038c9c4Sjoerg // - C, ObjC, and block pointers are definitely okay.
5738*e038c9c4Sjoerg // - References are definitely not okay.
5739*e038c9c4Sjoerg // - nullptr_t is weird, but acceptable.
5740*e038c9c4Sjoerg QualType RT = getFunctionOrMethodResultType(D);
5741*e038c9c4Sjoerg if (RT->hasPointerRepresentation() && !RT->isReferenceType())
5742*e038c9c4Sjoerg return true;
5743*e038c9c4Sjoerg
5744*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::err_attr_swift_error_return_type)
5745*e038c9c4Sjoerg << AL << AL.getArgAsIdent(0)->Ident->getName() << isa<ObjCMethodDecl>(D)
5746*e038c9c4Sjoerg << /*pointer*/ 1;
5747*e038c9c4Sjoerg return false;
5748*e038c9c4Sjoerg };
5749*e038c9c4Sjoerg
5750*e038c9c4Sjoerg auto hasIntegerResult = [](Sema &S, Decl *D, const ParsedAttr &AL) -> bool {
5751*e038c9c4Sjoerg QualType RT = getFunctionOrMethodResultType(D);
5752*e038c9c4Sjoerg if (RT->isIntegralType(S.Context))
5753*e038c9c4Sjoerg return true;
5754*e038c9c4Sjoerg
5755*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::err_attr_swift_error_return_type)
5756*e038c9c4Sjoerg << AL << AL.getArgAsIdent(0)->Ident->getName() << isa<ObjCMethodDecl>(D)
5757*e038c9c4Sjoerg << /*integral*/ 0;
5758*e038c9c4Sjoerg return false;
5759*e038c9c4Sjoerg };
5760*e038c9c4Sjoerg
5761*e038c9c4Sjoerg if (D->isInvalidDecl())
5762*e038c9c4Sjoerg return;
5763*e038c9c4Sjoerg
5764*e038c9c4Sjoerg IdentifierLoc *Loc = AL.getArgAsIdent(0);
5765*e038c9c4Sjoerg SwiftErrorAttr::ConventionKind Convention;
5766*e038c9c4Sjoerg if (!SwiftErrorAttr::ConvertStrToConventionKind(Loc->Ident->getName(),
5767*e038c9c4Sjoerg Convention)) {
5768*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
5769*e038c9c4Sjoerg << AL << Loc->Ident;
5770*e038c9c4Sjoerg return;
5771*e038c9c4Sjoerg }
5772*e038c9c4Sjoerg
5773*e038c9c4Sjoerg switch (Convention) {
5774*e038c9c4Sjoerg case SwiftErrorAttr::None:
5775*e038c9c4Sjoerg // No additional validation required.
5776*e038c9c4Sjoerg break;
5777*e038c9c4Sjoerg
5778*e038c9c4Sjoerg case SwiftErrorAttr::NonNullError:
5779*e038c9c4Sjoerg if (!hasErrorParameter(S, D, AL))
5780*e038c9c4Sjoerg return;
5781*e038c9c4Sjoerg break;
5782*e038c9c4Sjoerg
5783*e038c9c4Sjoerg case SwiftErrorAttr::NullResult:
5784*e038c9c4Sjoerg if (!hasErrorParameter(S, D, AL) || !hasPointerResult(S, D, AL))
5785*e038c9c4Sjoerg return;
5786*e038c9c4Sjoerg break;
5787*e038c9c4Sjoerg
5788*e038c9c4Sjoerg case SwiftErrorAttr::NonZeroResult:
5789*e038c9c4Sjoerg case SwiftErrorAttr::ZeroResult:
5790*e038c9c4Sjoerg if (!hasErrorParameter(S, D, AL) || !hasIntegerResult(S, D, AL))
5791*e038c9c4Sjoerg return;
5792*e038c9c4Sjoerg break;
5793*e038c9c4Sjoerg }
5794*e038c9c4Sjoerg
5795*e038c9c4Sjoerg D->addAttr(::new (S.Context) SwiftErrorAttr(S.Context, AL, Convention));
5796*e038c9c4Sjoerg }
5797*e038c9c4Sjoerg
checkSwiftAsyncErrorBlock(Sema & S,Decl * D,const SwiftAsyncErrorAttr * ErrorAttr,const SwiftAsyncAttr * AsyncAttr)5798*e038c9c4Sjoerg static void checkSwiftAsyncErrorBlock(Sema &S, Decl *D,
5799*e038c9c4Sjoerg const SwiftAsyncErrorAttr *ErrorAttr,
5800*e038c9c4Sjoerg const SwiftAsyncAttr *AsyncAttr) {
5801*e038c9c4Sjoerg if (AsyncAttr->getKind() == SwiftAsyncAttr::None) {
5802*e038c9c4Sjoerg if (ErrorAttr->getConvention() != SwiftAsyncErrorAttr::None) {
5803*e038c9c4Sjoerg S.Diag(AsyncAttr->getLocation(),
5804*e038c9c4Sjoerg diag::err_swift_async_error_without_swift_async)
5805*e038c9c4Sjoerg << AsyncAttr << isa<ObjCMethodDecl>(D);
5806*e038c9c4Sjoerg }
5807*e038c9c4Sjoerg return;
5808*e038c9c4Sjoerg }
5809*e038c9c4Sjoerg
5810*e038c9c4Sjoerg const ParmVarDecl *HandlerParam = getFunctionOrMethodParam(
5811*e038c9c4Sjoerg D, AsyncAttr->getCompletionHandlerIndex().getASTIndex());
5812*e038c9c4Sjoerg // handleSwiftAsyncAttr already verified the type is correct, so no need to
5813*e038c9c4Sjoerg // double-check it here.
5814*e038c9c4Sjoerg const auto *FuncTy = HandlerParam->getType()
5815*e038c9c4Sjoerg ->castAs<BlockPointerType>()
5816*e038c9c4Sjoerg ->getPointeeType()
5817*e038c9c4Sjoerg ->getAs<FunctionProtoType>();
5818*e038c9c4Sjoerg ArrayRef<QualType> BlockParams;
5819*e038c9c4Sjoerg if (FuncTy)
5820*e038c9c4Sjoerg BlockParams = FuncTy->getParamTypes();
5821*e038c9c4Sjoerg
5822*e038c9c4Sjoerg switch (ErrorAttr->getConvention()) {
5823*e038c9c4Sjoerg case SwiftAsyncErrorAttr::ZeroArgument:
5824*e038c9c4Sjoerg case SwiftAsyncErrorAttr::NonZeroArgument: {
5825*e038c9c4Sjoerg uint32_t ParamIdx = ErrorAttr->getHandlerParamIdx();
5826*e038c9c4Sjoerg if (ParamIdx == 0 || ParamIdx > BlockParams.size()) {
5827*e038c9c4Sjoerg S.Diag(ErrorAttr->getLocation(),
5828*e038c9c4Sjoerg diag::err_attribute_argument_out_of_bounds) << ErrorAttr << 2;
5829*e038c9c4Sjoerg return;
5830*e038c9c4Sjoerg }
5831*e038c9c4Sjoerg QualType ErrorParam = BlockParams[ParamIdx - 1];
5832*e038c9c4Sjoerg if (!ErrorParam->isIntegralType(S.Context)) {
5833*e038c9c4Sjoerg StringRef ConvStr =
5834*e038c9c4Sjoerg ErrorAttr->getConvention() == SwiftAsyncErrorAttr::ZeroArgument
5835*e038c9c4Sjoerg ? "zero_argument"
5836*e038c9c4Sjoerg : "nonzero_argument";
5837*e038c9c4Sjoerg S.Diag(ErrorAttr->getLocation(), diag::err_swift_async_error_non_integral)
5838*e038c9c4Sjoerg << ErrorAttr << ConvStr << ParamIdx << ErrorParam;
5839*e038c9c4Sjoerg return;
5840*e038c9c4Sjoerg }
5841*e038c9c4Sjoerg break;
5842*e038c9c4Sjoerg }
5843*e038c9c4Sjoerg case SwiftAsyncErrorAttr::NonNullError: {
5844*e038c9c4Sjoerg bool AnyErrorParams = false;
5845*e038c9c4Sjoerg for (QualType Param : BlockParams) {
5846*e038c9c4Sjoerg // Check for NSError *.
5847*e038c9c4Sjoerg if (const auto *ObjCPtrTy = Param->getAs<ObjCObjectPointerType>()) {
5848*e038c9c4Sjoerg if (const auto *ID = ObjCPtrTy->getInterfaceDecl()) {
5849*e038c9c4Sjoerg if (ID->getIdentifier() == S.getNSErrorIdent()) {
5850*e038c9c4Sjoerg AnyErrorParams = true;
5851*e038c9c4Sjoerg break;
5852*e038c9c4Sjoerg }
5853*e038c9c4Sjoerg }
5854*e038c9c4Sjoerg }
5855*e038c9c4Sjoerg // Check for CFError *.
5856*e038c9c4Sjoerg if (const auto *PtrTy = Param->getAs<PointerType>()) {
5857*e038c9c4Sjoerg if (const auto *RT = PtrTy->getPointeeType()->getAs<RecordType>()) {
5858*e038c9c4Sjoerg if (S.isCFError(RT->getDecl())) {
5859*e038c9c4Sjoerg AnyErrorParams = true;
5860*e038c9c4Sjoerg break;
5861*e038c9c4Sjoerg }
5862*e038c9c4Sjoerg }
5863*e038c9c4Sjoerg }
5864*e038c9c4Sjoerg }
5865*e038c9c4Sjoerg
5866*e038c9c4Sjoerg if (!AnyErrorParams) {
5867*e038c9c4Sjoerg S.Diag(ErrorAttr->getLocation(),
5868*e038c9c4Sjoerg diag::err_swift_async_error_no_error_parameter)
5869*e038c9c4Sjoerg << ErrorAttr << isa<ObjCMethodDecl>(D);
5870*e038c9c4Sjoerg return;
5871*e038c9c4Sjoerg }
5872*e038c9c4Sjoerg break;
5873*e038c9c4Sjoerg }
5874*e038c9c4Sjoerg case SwiftAsyncErrorAttr::None:
5875*e038c9c4Sjoerg break;
5876*e038c9c4Sjoerg }
5877*e038c9c4Sjoerg }
5878*e038c9c4Sjoerg
handleSwiftAsyncError(Sema & S,Decl * D,const ParsedAttr & AL)5879*e038c9c4Sjoerg static void handleSwiftAsyncError(Sema &S, Decl *D, const ParsedAttr &AL) {
5880*e038c9c4Sjoerg IdentifierLoc *IDLoc = AL.getArgAsIdent(0);
5881*e038c9c4Sjoerg SwiftAsyncErrorAttr::ConventionKind ConvKind;
5882*e038c9c4Sjoerg if (!SwiftAsyncErrorAttr::ConvertStrToConventionKind(IDLoc->Ident->getName(),
5883*e038c9c4Sjoerg ConvKind)) {
5884*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
5885*e038c9c4Sjoerg << AL << IDLoc->Ident;
5886*e038c9c4Sjoerg return;
5887*e038c9c4Sjoerg }
5888*e038c9c4Sjoerg
5889*e038c9c4Sjoerg uint32_t ParamIdx = 0;
5890*e038c9c4Sjoerg switch (ConvKind) {
5891*e038c9c4Sjoerg case SwiftAsyncErrorAttr::ZeroArgument:
5892*e038c9c4Sjoerg case SwiftAsyncErrorAttr::NonZeroArgument: {
5893*e038c9c4Sjoerg if (!AL.checkExactlyNumArgs(S, 2))
5894*e038c9c4Sjoerg return;
5895*e038c9c4Sjoerg
5896*e038c9c4Sjoerg Expr *IdxExpr = AL.getArgAsExpr(1);
5897*e038c9c4Sjoerg if (!checkUInt32Argument(S, AL, IdxExpr, ParamIdx))
5898*e038c9c4Sjoerg return;
5899*e038c9c4Sjoerg break;
5900*e038c9c4Sjoerg }
5901*e038c9c4Sjoerg case SwiftAsyncErrorAttr::NonNullError:
5902*e038c9c4Sjoerg case SwiftAsyncErrorAttr::None: {
5903*e038c9c4Sjoerg if (!AL.checkExactlyNumArgs(S, 1))
5904*e038c9c4Sjoerg return;
5905*e038c9c4Sjoerg break;
5906*e038c9c4Sjoerg }
5907*e038c9c4Sjoerg }
5908*e038c9c4Sjoerg
5909*e038c9c4Sjoerg auto *ErrorAttr =
5910*e038c9c4Sjoerg ::new (S.Context) SwiftAsyncErrorAttr(S.Context, AL, ConvKind, ParamIdx);
5911*e038c9c4Sjoerg D->addAttr(ErrorAttr);
5912*e038c9c4Sjoerg
5913*e038c9c4Sjoerg if (auto *AsyncAttr = D->getAttr<SwiftAsyncAttr>())
5914*e038c9c4Sjoerg checkSwiftAsyncErrorBlock(S, D, ErrorAttr, AsyncAttr);
5915*e038c9c4Sjoerg }
5916*e038c9c4Sjoerg
5917*e038c9c4Sjoerg // For a function, this will validate a compound Swift name, e.g.
5918*e038c9c4Sjoerg // <code>init(foo:bar:baz:)</code> or <code>controllerForName(_:)</code>, and
5919*e038c9c4Sjoerg // the function will output the number of parameter names, and whether this is a
5920*e038c9c4Sjoerg // single-arg initializer.
5921*e038c9c4Sjoerg //
5922*e038c9c4Sjoerg // For a type, enum constant, property, or variable declaration, this will
5923*e038c9c4Sjoerg // validate either a simple identifier, or a qualified
5924*e038c9c4Sjoerg // <code>context.identifier</code> name.
5925*e038c9c4Sjoerg static bool
validateSwiftFunctionName(Sema & S,const ParsedAttr & AL,SourceLocation Loc,StringRef Name,unsigned & SwiftParamCount,bool & IsSingleParamInit)5926*e038c9c4Sjoerg validateSwiftFunctionName(Sema &S, const ParsedAttr &AL, SourceLocation Loc,
5927*e038c9c4Sjoerg StringRef Name, unsigned &SwiftParamCount,
5928*e038c9c4Sjoerg bool &IsSingleParamInit) {
5929*e038c9c4Sjoerg SwiftParamCount = 0;
5930*e038c9c4Sjoerg IsSingleParamInit = false;
5931*e038c9c4Sjoerg
5932*e038c9c4Sjoerg // Check whether this will be mapped to a getter or setter of a property.
5933*e038c9c4Sjoerg bool IsGetter = false, IsSetter = false;
5934*e038c9c4Sjoerg if (Name.startswith("getter:")) {
5935*e038c9c4Sjoerg IsGetter = true;
5936*e038c9c4Sjoerg Name = Name.substr(7);
5937*e038c9c4Sjoerg } else if (Name.startswith("setter:")) {
5938*e038c9c4Sjoerg IsSetter = true;
5939*e038c9c4Sjoerg Name = Name.substr(7);
5940*e038c9c4Sjoerg }
5941*e038c9c4Sjoerg
5942*e038c9c4Sjoerg if (Name.back() != ')') {
5943*e038c9c4Sjoerg S.Diag(Loc, diag::warn_attr_swift_name_function) << AL;
5944*e038c9c4Sjoerg return false;
5945*e038c9c4Sjoerg }
5946*e038c9c4Sjoerg
5947*e038c9c4Sjoerg bool IsMember = false;
5948*e038c9c4Sjoerg StringRef ContextName, BaseName, Parameters;
5949*e038c9c4Sjoerg
5950*e038c9c4Sjoerg std::tie(BaseName, Parameters) = Name.split('(');
5951*e038c9c4Sjoerg
5952*e038c9c4Sjoerg // Split at the first '.', if it exists, which separates the context name
5953*e038c9c4Sjoerg // from the base name.
5954*e038c9c4Sjoerg std::tie(ContextName, BaseName) = BaseName.split('.');
5955*e038c9c4Sjoerg if (BaseName.empty()) {
5956*e038c9c4Sjoerg BaseName = ContextName;
5957*e038c9c4Sjoerg ContextName = StringRef();
5958*e038c9c4Sjoerg } else if (ContextName.empty() || !isValidIdentifier(ContextName)) {
5959*e038c9c4Sjoerg S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
5960*e038c9c4Sjoerg << AL << /*context*/ 1;
5961*e038c9c4Sjoerg return false;
5962*e038c9c4Sjoerg } else {
5963*e038c9c4Sjoerg IsMember = true;
5964*e038c9c4Sjoerg }
5965*e038c9c4Sjoerg
5966*e038c9c4Sjoerg if (!isValidIdentifier(BaseName) || BaseName == "_") {
5967*e038c9c4Sjoerg S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
5968*e038c9c4Sjoerg << AL << /*basename*/ 0;
5969*e038c9c4Sjoerg return false;
5970*e038c9c4Sjoerg }
5971*e038c9c4Sjoerg
5972*e038c9c4Sjoerg bool IsSubscript = BaseName == "subscript";
5973*e038c9c4Sjoerg // A subscript accessor must be a getter or setter.
5974*e038c9c4Sjoerg if (IsSubscript && !IsGetter && !IsSetter) {
5975*e038c9c4Sjoerg S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter)
5976*e038c9c4Sjoerg << AL << /* getter or setter */ 0;
5977*e038c9c4Sjoerg return false;
5978*e038c9c4Sjoerg }
5979*e038c9c4Sjoerg
5980*e038c9c4Sjoerg if (Parameters.empty()) {
5981*e038c9c4Sjoerg S.Diag(Loc, diag::warn_attr_swift_name_missing_parameters) << AL;
5982*e038c9c4Sjoerg return false;
5983*e038c9c4Sjoerg }
5984*e038c9c4Sjoerg
5985*e038c9c4Sjoerg assert(Parameters.back() == ')' && "expected ')'");
5986*e038c9c4Sjoerg Parameters = Parameters.drop_back(); // ')'
5987*e038c9c4Sjoerg
5988*e038c9c4Sjoerg if (Parameters.empty()) {
5989*e038c9c4Sjoerg // Setters and subscripts must have at least one parameter.
5990*e038c9c4Sjoerg if (IsSubscript) {
5991*e038c9c4Sjoerg S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter)
5992*e038c9c4Sjoerg << AL << /* have at least one parameter */1;
5993*e038c9c4Sjoerg return false;
5994*e038c9c4Sjoerg }
5995*e038c9c4Sjoerg
5996*e038c9c4Sjoerg if (IsSetter) {
5997*e038c9c4Sjoerg S.Diag(Loc, diag::warn_attr_swift_name_setter_parameters) << AL;
5998*e038c9c4Sjoerg return false;
5999*e038c9c4Sjoerg }
6000*e038c9c4Sjoerg
6001*e038c9c4Sjoerg return true;
6002*e038c9c4Sjoerg }
6003*e038c9c4Sjoerg
6004*e038c9c4Sjoerg if (Parameters.back() != ':') {
6005*e038c9c4Sjoerg S.Diag(Loc, diag::warn_attr_swift_name_function) << AL;
6006*e038c9c4Sjoerg return false;
6007*e038c9c4Sjoerg }
6008*e038c9c4Sjoerg
6009*e038c9c4Sjoerg StringRef CurrentParam;
6010*e038c9c4Sjoerg llvm::Optional<unsigned> SelfLocation;
6011*e038c9c4Sjoerg unsigned NewValueCount = 0;
6012*e038c9c4Sjoerg llvm::Optional<unsigned> NewValueLocation;
6013*e038c9c4Sjoerg do {
6014*e038c9c4Sjoerg std::tie(CurrentParam, Parameters) = Parameters.split(':');
6015*e038c9c4Sjoerg
6016*e038c9c4Sjoerg if (!isValidIdentifier(CurrentParam)) {
6017*e038c9c4Sjoerg S.Diag(Loc, diag::warn_attr_swift_name_invalid_identifier)
6018*e038c9c4Sjoerg << AL << /*parameter*/2;
6019*e038c9c4Sjoerg return false;
6020*e038c9c4Sjoerg }
6021*e038c9c4Sjoerg
6022*e038c9c4Sjoerg if (IsMember && CurrentParam == "self") {
6023*e038c9c4Sjoerg // "self" indicates the "self" argument for a member.
6024*e038c9c4Sjoerg
6025*e038c9c4Sjoerg // More than one "self"?
6026*e038c9c4Sjoerg if (SelfLocation) {
6027*e038c9c4Sjoerg S.Diag(Loc, diag::warn_attr_swift_name_multiple_selfs) << AL;
6028*e038c9c4Sjoerg return false;
6029*e038c9c4Sjoerg }
6030*e038c9c4Sjoerg
6031*e038c9c4Sjoerg // The "self" location is the current parameter.
6032*e038c9c4Sjoerg SelfLocation = SwiftParamCount;
6033*e038c9c4Sjoerg } else if (CurrentParam == "newValue") {
6034*e038c9c4Sjoerg // "newValue" indicates the "newValue" argument for a setter.
6035*e038c9c4Sjoerg
6036*e038c9c4Sjoerg // There should only be one 'newValue', but it's only significant for
6037*e038c9c4Sjoerg // subscript accessors, so don't error right away.
6038*e038c9c4Sjoerg ++NewValueCount;
6039*e038c9c4Sjoerg
6040*e038c9c4Sjoerg NewValueLocation = SwiftParamCount;
6041*e038c9c4Sjoerg }
6042*e038c9c4Sjoerg
6043*e038c9c4Sjoerg ++SwiftParamCount;
6044*e038c9c4Sjoerg } while (!Parameters.empty());
6045*e038c9c4Sjoerg
6046*e038c9c4Sjoerg // Only instance subscripts are currently supported.
6047*e038c9c4Sjoerg if (IsSubscript && !SelfLocation) {
6048*e038c9c4Sjoerg S.Diag(Loc, diag::warn_attr_swift_name_subscript_invalid_parameter)
6049*e038c9c4Sjoerg << AL << /*have a 'self:' parameter*/2;
6050*e038c9c4Sjoerg return false;
6051*e038c9c4Sjoerg }
6052*e038c9c4Sjoerg
6053*e038c9c4Sjoerg IsSingleParamInit =
6054*e038c9c4Sjoerg SwiftParamCount == 1 && BaseName == "init" && CurrentParam != "_";
6055*e038c9c4Sjoerg
6056*e038c9c4Sjoerg // Check the number of parameters for a getter/setter.
6057*e038c9c4Sjoerg if (IsGetter || IsSetter) {
6058*e038c9c4Sjoerg // Setters have one parameter for the new value.
6059*e038c9c4Sjoerg unsigned NumExpectedParams = IsGetter ? 0 : 1;
6060*e038c9c4Sjoerg unsigned ParamDiag =
6061*e038c9c4Sjoerg IsGetter ? diag::warn_attr_swift_name_getter_parameters
6062*e038c9c4Sjoerg : diag::warn_attr_swift_name_setter_parameters;
6063*e038c9c4Sjoerg
6064*e038c9c4Sjoerg // Instance methods have one parameter for "self".
6065*e038c9c4Sjoerg if (SelfLocation)
6066*e038c9c4Sjoerg ++NumExpectedParams;
6067*e038c9c4Sjoerg
6068*e038c9c4Sjoerg // Subscripts may have additional parameters beyond the expected params for
6069*e038c9c4Sjoerg // the index.
6070*e038c9c4Sjoerg if (IsSubscript) {
6071*e038c9c4Sjoerg if (SwiftParamCount < NumExpectedParams) {
6072*e038c9c4Sjoerg S.Diag(Loc, ParamDiag) << AL;
6073*e038c9c4Sjoerg return false;
6074*e038c9c4Sjoerg }
6075*e038c9c4Sjoerg
6076*e038c9c4Sjoerg // A subscript setter must explicitly label its newValue parameter to
6077*e038c9c4Sjoerg // distinguish it from index parameters.
6078*e038c9c4Sjoerg if (IsSetter) {
6079*e038c9c4Sjoerg if (!NewValueLocation) {
6080*e038c9c4Sjoerg S.Diag(Loc, diag::warn_attr_swift_name_subscript_setter_no_newValue)
6081*e038c9c4Sjoerg << AL;
6082*e038c9c4Sjoerg return false;
6083*e038c9c4Sjoerg }
6084*e038c9c4Sjoerg if (NewValueCount > 1) {
6085*e038c9c4Sjoerg S.Diag(Loc, diag::warn_attr_swift_name_subscript_setter_multiple_newValues)
6086*e038c9c4Sjoerg << AL;
6087*e038c9c4Sjoerg return false;
6088*e038c9c4Sjoerg }
6089*e038c9c4Sjoerg } else {
6090*e038c9c4Sjoerg // Subscript getters should have no 'newValue:' parameter.
6091*e038c9c4Sjoerg if (NewValueLocation) {
6092*e038c9c4Sjoerg S.Diag(Loc, diag::warn_attr_swift_name_subscript_getter_newValue)
6093*e038c9c4Sjoerg << AL;
6094*e038c9c4Sjoerg return false;
6095*e038c9c4Sjoerg }
6096*e038c9c4Sjoerg }
6097*e038c9c4Sjoerg } else {
6098*e038c9c4Sjoerg // Property accessors must have exactly the number of expected params.
6099*e038c9c4Sjoerg if (SwiftParamCount != NumExpectedParams) {
6100*e038c9c4Sjoerg S.Diag(Loc, ParamDiag) << AL;
6101*e038c9c4Sjoerg return false;
6102*e038c9c4Sjoerg }
6103*e038c9c4Sjoerg }
6104*e038c9c4Sjoerg }
6105*e038c9c4Sjoerg
6106*e038c9c4Sjoerg return true;
6107*e038c9c4Sjoerg }
6108*e038c9c4Sjoerg
DiagnoseSwiftName(Decl * D,StringRef Name,SourceLocation Loc,const ParsedAttr & AL,bool IsAsync)6109*e038c9c4Sjoerg bool Sema::DiagnoseSwiftName(Decl *D, StringRef Name, SourceLocation Loc,
6110*e038c9c4Sjoerg const ParsedAttr &AL, bool IsAsync) {
6111*e038c9c4Sjoerg if (isa<ObjCMethodDecl>(D) || isa<FunctionDecl>(D)) {
6112*e038c9c4Sjoerg ArrayRef<ParmVarDecl*> Params;
6113*e038c9c4Sjoerg unsigned ParamCount;
6114*e038c9c4Sjoerg
6115*e038c9c4Sjoerg if (const auto *Method = dyn_cast<ObjCMethodDecl>(D)) {
6116*e038c9c4Sjoerg ParamCount = Method->getSelector().getNumArgs();
6117*e038c9c4Sjoerg Params = Method->parameters().slice(0, ParamCount);
6118*e038c9c4Sjoerg } else {
6119*e038c9c4Sjoerg const auto *F = cast<FunctionDecl>(D);
6120*e038c9c4Sjoerg
6121*e038c9c4Sjoerg ParamCount = F->getNumParams();
6122*e038c9c4Sjoerg Params = F->parameters();
6123*e038c9c4Sjoerg
6124*e038c9c4Sjoerg if (!F->hasWrittenPrototype()) {
6125*e038c9c4Sjoerg Diag(Loc, diag::warn_attribute_wrong_decl_type) << AL
6126*e038c9c4Sjoerg << ExpectedFunctionWithProtoType;
6127*e038c9c4Sjoerg return false;
6128*e038c9c4Sjoerg }
6129*e038c9c4Sjoerg }
6130*e038c9c4Sjoerg
6131*e038c9c4Sjoerg // The async name drops the last callback parameter.
6132*e038c9c4Sjoerg if (IsAsync) {
6133*e038c9c4Sjoerg if (ParamCount == 0) {
6134*e038c9c4Sjoerg Diag(Loc, diag::warn_attr_swift_name_decl_missing_params)
6135*e038c9c4Sjoerg << AL << isa<ObjCMethodDecl>(D);
6136*e038c9c4Sjoerg return false;
6137*e038c9c4Sjoerg }
6138*e038c9c4Sjoerg ParamCount -= 1;
6139*e038c9c4Sjoerg }
6140*e038c9c4Sjoerg
6141*e038c9c4Sjoerg unsigned SwiftParamCount;
6142*e038c9c4Sjoerg bool IsSingleParamInit;
6143*e038c9c4Sjoerg if (!validateSwiftFunctionName(*this, AL, Loc, Name,
6144*e038c9c4Sjoerg SwiftParamCount, IsSingleParamInit))
6145*e038c9c4Sjoerg return false;
6146*e038c9c4Sjoerg
6147*e038c9c4Sjoerg bool ParamCountValid;
6148*e038c9c4Sjoerg if (SwiftParamCount == ParamCount) {
6149*e038c9c4Sjoerg ParamCountValid = true;
6150*e038c9c4Sjoerg } else if (SwiftParamCount > ParamCount) {
6151*e038c9c4Sjoerg ParamCountValid = IsSingleParamInit && ParamCount == 0;
6152*e038c9c4Sjoerg } else {
6153*e038c9c4Sjoerg // We have fewer Swift parameters than Objective-C parameters, but that
6154*e038c9c4Sjoerg // might be because we've transformed some of them. Check for potential
6155*e038c9c4Sjoerg // "out" parameters and err on the side of not warning.
6156*e038c9c4Sjoerg unsigned MaybeOutParamCount =
6157*e038c9c4Sjoerg std::count_if(Params.begin(), Params.end(),
6158*e038c9c4Sjoerg [](const ParmVarDecl *Param) -> bool {
6159*e038c9c4Sjoerg QualType ParamTy = Param->getType();
6160*e038c9c4Sjoerg if (ParamTy->isReferenceType() || ParamTy->isPointerType())
6161*e038c9c4Sjoerg return !ParamTy->getPointeeType().isConstQualified();
6162*e038c9c4Sjoerg return false;
6163*e038c9c4Sjoerg });
6164*e038c9c4Sjoerg
6165*e038c9c4Sjoerg ParamCountValid = SwiftParamCount + MaybeOutParamCount >= ParamCount;
6166*e038c9c4Sjoerg }
6167*e038c9c4Sjoerg
6168*e038c9c4Sjoerg if (!ParamCountValid) {
6169*e038c9c4Sjoerg Diag(Loc, diag::warn_attr_swift_name_num_params)
6170*e038c9c4Sjoerg << (SwiftParamCount > ParamCount) << AL << ParamCount
6171*e038c9c4Sjoerg << SwiftParamCount;
6172*e038c9c4Sjoerg return false;
6173*e038c9c4Sjoerg }
6174*e038c9c4Sjoerg } else if ((isa<EnumConstantDecl>(D) || isa<ObjCProtocolDecl>(D) ||
6175*e038c9c4Sjoerg isa<ObjCInterfaceDecl>(D) || isa<ObjCPropertyDecl>(D) ||
6176*e038c9c4Sjoerg isa<VarDecl>(D) || isa<TypedefNameDecl>(D) || isa<TagDecl>(D) ||
6177*e038c9c4Sjoerg isa<IndirectFieldDecl>(D) || isa<FieldDecl>(D)) &&
6178*e038c9c4Sjoerg !IsAsync) {
6179*e038c9c4Sjoerg StringRef ContextName, BaseName;
6180*e038c9c4Sjoerg
6181*e038c9c4Sjoerg std::tie(ContextName, BaseName) = Name.split('.');
6182*e038c9c4Sjoerg if (BaseName.empty()) {
6183*e038c9c4Sjoerg BaseName = ContextName;
6184*e038c9c4Sjoerg ContextName = StringRef();
6185*e038c9c4Sjoerg } else if (!isValidIdentifier(ContextName)) {
6186*e038c9c4Sjoerg Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) << AL
6187*e038c9c4Sjoerg << /*context*/1;
6188*e038c9c4Sjoerg return false;
6189*e038c9c4Sjoerg }
6190*e038c9c4Sjoerg
6191*e038c9c4Sjoerg if (!isValidIdentifier(BaseName)) {
6192*e038c9c4Sjoerg Diag(Loc, diag::warn_attr_swift_name_invalid_identifier) << AL
6193*e038c9c4Sjoerg << /*basename*/0;
6194*e038c9c4Sjoerg return false;
6195*e038c9c4Sjoerg }
6196*e038c9c4Sjoerg } else {
6197*e038c9c4Sjoerg Diag(Loc, diag::warn_attr_swift_name_decl_kind) << AL;
6198*e038c9c4Sjoerg return false;
6199*e038c9c4Sjoerg }
6200*e038c9c4Sjoerg return true;
6201*e038c9c4Sjoerg }
6202*e038c9c4Sjoerg
handleSwiftName(Sema & S,Decl * D,const ParsedAttr & AL)6203*e038c9c4Sjoerg static void handleSwiftName(Sema &S, Decl *D, const ParsedAttr &AL) {
6204*e038c9c4Sjoerg StringRef Name;
6205*e038c9c4Sjoerg SourceLocation Loc;
6206*e038c9c4Sjoerg if (!S.checkStringLiteralArgumentAttr(AL, 0, Name, &Loc))
6207*e038c9c4Sjoerg return;
6208*e038c9c4Sjoerg
6209*e038c9c4Sjoerg if (!S.DiagnoseSwiftName(D, Name, Loc, AL, /*IsAsync=*/false))
6210*e038c9c4Sjoerg return;
6211*e038c9c4Sjoerg
6212*e038c9c4Sjoerg D->addAttr(::new (S.Context) SwiftNameAttr(S.Context, AL, Name));
6213*e038c9c4Sjoerg }
6214*e038c9c4Sjoerg
handleSwiftAsyncName(Sema & S,Decl * D,const ParsedAttr & AL)6215*e038c9c4Sjoerg static void handleSwiftAsyncName(Sema &S, Decl *D, const ParsedAttr &AL) {
6216*e038c9c4Sjoerg StringRef Name;
6217*e038c9c4Sjoerg SourceLocation Loc;
6218*e038c9c4Sjoerg if (!S.checkStringLiteralArgumentAttr(AL, 0, Name, &Loc))
6219*e038c9c4Sjoerg return;
6220*e038c9c4Sjoerg
6221*e038c9c4Sjoerg if (!S.DiagnoseSwiftName(D, Name, Loc, AL, /*IsAsync=*/true))
6222*e038c9c4Sjoerg return;
6223*e038c9c4Sjoerg
6224*e038c9c4Sjoerg D->addAttr(::new (S.Context) SwiftAsyncNameAttr(S.Context, AL, Name));
6225*e038c9c4Sjoerg }
6226*e038c9c4Sjoerg
handleSwiftNewType(Sema & S,Decl * D,const ParsedAttr & AL)6227*e038c9c4Sjoerg static void handleSwiftNewType(Sema &S, Decl *D, const ParsedAttr &AL) {
6228*e038c9c4Sjoerg // Make sure that there is an identifier as the annotation's single argument.
6229*e038c9c4Sjoerg if (!AL.checkExactlyNumArgs(S, 1))
6230*e038c9c4Sjoerg return;
6231*e038c9c4Sjoerg
6232*e038c9c4Sjoerg if (!AL.isArgIdent(0)) {
6233*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
6234*e038c9c4Sjoerg << AL << AANT_ArgumentIdentifier;
6235*e038c9c4Sjoerg return;
6236*e038c9c4Sjoerg }
6237*e038c9c4Sjoerg
6238*e038c9c4Sjoerg SwiftNewTypeAttr::NewtypeKind Kind;
6239*e038c9c4Sjoerg IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
6240*e038c9c4Sjoerg if (!SwiftNewTypeAttr::ConvertStrToNewtypeKind(II->getName(), Kind)) {
6241*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II;
6242*e038c9c4Sjoerg return;
6243*e038c9c4Sjoerg }
6244*e038c9c4Sjoerg
6245*e038c9c4Sjoerg if (!isa<TypedefNameDecl>(D)) {
6246*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type_str)
6247*e038c9c4Sjoerg << AL << "typedefs";
6248*e038c9c4Sjoerg return;
6249*e038c9c4Sjoerg }
6250*e038c9c4Sjoerg
6251*e038c9c4Sjoerg D->addAttr(::new (S.Context) SwiftNewTypeAttr(S.Context, AL, Kind));
6252*e038c9c4Sjoerg }
6253*e038c9c4Sjoerg
handleSwiftAsyncAttr(Sema & S,Decl * D,const ParsedAttr & AL)6254*e038c9c4Sjoerg static void handleSwiftAsyncAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
6255*e038c9c4Sjoerg if (!AL.isArgIdent(0)) {
6256*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
6257*e038c9c4Sjoerg << AL << 1 << AANT_ArgumentIdentifier;
6258*e038c9c4Sjoerg return;
6259*e038c9c4Sjoerg }
6260*e038c9c4Sjoerg
6261*e038c9c4Sjoerg SwiftAsyncAttr::Kind Kind;
6262*e038c9c4Sjoerg IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
6263*e038c9c4Sjoerg if (!SwiftAsyncAttr::ConvertStrToKind(II->getName(), Kind)) {
6264*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::err_swift_async_no_access) << AL << II;
6265*e038c9c4Sjoerg return;
6266*e038c9c4Sjoerg }
6267*e038c9c4Sjoerg
6268*e038c9c4Sjoerg ParamIdx Idx;
6269*e038c9c4Sjoerg if (Kind == SwiftAsyncAttr::None) {
6270*e038c9c4Sjoerg // If this is 'none', then there shouldn't be any additional arguments.
6271*e038c9c4Sjoerg if (!AL.checkExactlyNumArgs(S, 1))
6272*e038c9c4Sjoerg return;
6273*e038c9c4Sjoerg } else {
6274*e038c9c4Sjoerg // Non-none swift_async requires a completion handler index argument.
6275*e038c9c4Sjoerg if (!AL.checkExactlyNumArgs(S, 2))
6276*e038c9c4Sjoerg return;
6277*e038c9c4Sjoerg
6278*e038c9c4Sjoerg Expr *HandlerIdx = AL.getArgAsExpr(1);
6279*e038c9c4Sjoerg if (!checkFunctionOrMethodParameterIndex(S, D, AL, 2, HandlerIdx, Idx))
6280*e038c9c4Sjoerg return;
6281*e038c9c4Sjoerg
6282*e038c9c4Sjoerg const ParmVarDecl *CompletionBlock =
6283*e038c9c4Sjoerg getFunctionOrMethodParam(D, Idx.getASTIndex());
6284*e038c9c4Sjoerg QualType CompletionBlockType = CompletionBlock->getType();
6285*e038c9c4Sjoerg if (!CompletionBlockType->isBlockPointerType()) {
6286*e038c9c4Sjoerg S.Diag(CompletionBlock->getLocation(),
6287*e038c9c4Sjoerg diag::err_swift_async_bad_block_type)
6288*e038c9c4Sjoerg << CompletionBlock->getType();
6289*e038c9c4Sjoerg return;
6290*e038c9c4Sjoerg }
6291*e038c9c4Sjoerg QualType BlockTy =
6292*e038c9c4Sjoerg CompletionBlockType->castAs<BlockPointerType>()->getPointeeType();
6293*e038c9c4Sjoerg if (!BlockTy->castAs<FunctionType>()->getReturnType()->isVoidType()) {
6294*e038c9c4Sjoerg S.Diag(CompletionBlock->getLocation(),
6295*e038c9c4Sjoerg diag::err_swift_async_bad_block_type)
6296*e038c9c4Sjoerg << CompletionBlock->getType();
6297*e038c9c4Sjoerg return;
6298*e038c9c4Sjoerg }
6299*e038c9c4Sjoerg }
6300*e038c9c4Sjoerg
6301*e038c9c4Sjoerg auto *AsyncAttr =
6302*e038c9c4Sjoerg ::new (S.Context) SwiftAsyncAttr(S.Context, AL, Kind, Idx);
6303*e038c9c4Sjoerg D->addAttr(AsyncAttr);
6304*e038c9c4Sjoerg
6305*e038c9c4Sjoerg if (auto *ErrorAttr = D->getAttr<SwiftAsyncErrorAttr>())
6306*e038c9c4Sjoerg checkSwiftAsyncErrorBlock(S, D, ErrorAttr, AsyncAttr);
6307*e038c9c4Sjoerg }
6308*e038c9c4Sjoerg
63097330f729Sjoerg //===----------------------------------------------------------------------===//
63107330f729Sjoerg // Microsoft specific attribute handlers.
63117330f729Sjoerg //===----------------------------------------------------------------------===//
63127330f729Sjoerg
mergeUuidAttr(Decl * D,const AttributeCommonInfo & CI,StringRef UuidAsWritten,MSGuidDecl * GuidDecl)63137330f729Sjoerg UuidAttr *Sema::mergeUuidAttr(Decl *D, const AttributeCommonInfo &CI,
6314*e038c9c4Sjoerg StringRef UuidAsWritten, MSGuidDecl *GuidDecl) {
63157330f729Sjoerg if (const auto *UA = D->getAttr<UuidAttr>()) {
6316*e038c9c4Sjoerg if (declaresSameEntity(UA->getGuidDecl(), GuidDecl))
63177330f729Sjoerg return nullptr;
6318*e038c9c4Sjoerg if (!UA->getGuid().empty()) {
63197330f729Sjoerg Diag(UA->getLocation(), diag::err_mismatched_uuid);
63207330f729Sjoerg Diag(CI.getLoc(), diag::note_previous_uuid);
63217330f729Sjoerg D->dropAttr<UuidAttr>();
63227330f729Sjoerg }
6323*e038c9c4Sjoerg }
63247330f729Sjoerg
6325*e038c9c4Sjoerg return ::new (Context) UuidAttr(Context, CI, UuidAsWritten, GuidDecl);
63267330f729Sjoerg }
63277330f729Sjoerg
handleUuidAttr(Sema & S,Decl * D,const ParsedAttr & AL)63287330f729Sjoerg static void handleUuidAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
63297330f729Sjoerg if (!S.LangOpts.CPlusPlus) {
63307330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang)
63317330f729Sjoerg << AL << AttributeLangSupport::C;
63327330f729Sjoerg return;
63337330f729Sjoerg }
63347330f729Sjoerg
6335*e038c9c4Sjoerg StringRef OrigStrRef;
63367330f729Sjoerg SourceLocation LiteralLoc;
6337*e038c9c4Sjoerg if (!S.checkStringLiteralArgumentAttr(AL, 0, OrigStrRef, &LiteralLoc))
63387330f729Sjoerg return;
63397330f729Sjoerg
63407330f729Sjoerg // GUID format is "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" or
63417330f729Sjoerg // "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}", normalize to the former.
6342*e038c9c4Sjoerg StringRef StrRef = OrigStrRef;
63437330f729Sjoerg if (StrRef.size() == 38 && StrRef.front() == '{' && StrRef.back() == '}')
63447330f729Sjoerg StrRef = StrRef.drop_front().drop_back();
63457330f729Sjoerg
63467330f729Sjoerg // Validate GUID length.
63477330f729Sjoerg if (StrRef.size() != 36) {
63487330f729Sjoerg S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid);
63497330f729Sjoerg return;
63507330f729Sjoerg }
63517330f729Sjoerg
63527330f729Sjoerg for (unsigned i = 0; i < 36; ++i) {
63537330f729Sjoerg if (i == 8 || i == 13 || i == 18 || i == 23) {
63547330f729Sjoerg if (StrRef[i] != '-') {
63557330f729Sjoerg S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid);
63567330f729Sjoerg return;
63577330f729Sjoerg }
63587330f729Sjoerg } else if (!isHexDigit(StrRef[i])) {
63597330f729Sjoerg S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid);
63607330f729Sjoerg return;
63617330f729Sjoerg }
63627330f729Sjoerg }
63637330f729Sjoerg
6364*e038c9c4Sjoerg // Convert to our parsed format and canonicalize.
6365*e038c9c4Sjoerg MSGuidDecl::Parts Parsed;
6366*e038c9c4Sjoerg StrRef.substr(0, 8).getAsInteger(16, Parsed.Part1);
6367*e038c9c4Sjoerg StrRef.substr(9, 4).getAsInteger(16, Parsed.Part2);
6368*e038c9c4Sjoerg StrRef.substr(14, 4).getAsInteger(16, Parsed.Part3);
6369*e038c9c4Sjoerg for (unsigned i = 0; i != 8; ++i)
6370*e038c9c4Sjoerg StrRef.substr(19 + 2 * i + (i >= 2 ? 1 : 0), 2)
6371*e038c9c4Sjoerg .getAsInteger(16, Parsed.Part4And5[i]);
6372*e038c9c4Sjoerg MSGuidDecl *Guid = S.Context.getMSGuidDecl(Parsed);
6373*e038c9c4Sjoerg
63747330f729Sjoerg // FIXME: It'd be nice to also emit a fixit removing uuid(...) (and, if it's
63757330f729Sjoerg // the only thing in the [] list, the [] too), and add an insertion of
63767330f729Sjoerg // __declspec(uuid(...)). But sadly, neither the SourceLocs of the commas
63777330f729Sjoerg // separating attributes nor of the [ and the ] are in the AST.
63787330f729Sjoerg // Cf "SourceLocations of attribute list delimiters - [[ ... , ... ]] etc"
63797330f729Sjoerg // on cfe-dev.
63807330f729Sjoerg if (AL.isMicrosoftAttribute()) // Check for [uuid(...)] spelling.
63817330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_atl_uuid_deprecated);
63827330f729Sjoerg
6383*e038c9c4Sjoerg UuidAttr *UA = S.mergeUuidAttr(D, AL, OrigStrRef, Guid);
63847330f729Sjoerg if (UA)
63857330f729Sjoerg D->addAttr(UA);
63867330f729Sjoerg }
63877330f729Sjoerg
handleMSInheritanceAttr(Sema & S,Decl * D,const ParsedAttr & AL)63887330f729Sjoerg static void handleMSInheritanceAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
63897330f729Sjoerg if (!S.LangOpts.CPlusPlus) {
63907330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_not_supported_in_lang)
63917330f729Sjoerg << AL << AttributeLangSupport::C;
63927330f729Sjoerg return;
63937330f729Sjoerg }
63947330f729Sjoerg MSInheritanceAttr *IA = S.mergeMSInheritanceAttr(
6395*e038c9c4Sjoerg D, AL, /*BestCase=*/true, (MSInheritanceModel)AL.getSemanticSpelling());
63967330f729Sjoerg if (IA) {
63977330f729Sjoerg D->addAttr(IA);
63987330f729Sjoerg S.Consumer.AssignInheritanceModel(cast<CXXRecordDecl>(D));
63997330f729Sjoerg }
64007330f729Sjoerg }
64017330f729Sjoerg
handleDeclspecThreadAttr(Sema & S,Decl * D,const ParsedAttr & AL)64027330f729Sjoerg static void handleDeclspecThreadAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
64037330f729Sjoerg const auto *VD = cast<VarDecl>(D);
64047330f729Sjoerg if (!S.Context.getTargetInfo().isTLSSupported()) {
64057330f729Sjoerg S.Diag(AL.getLoc(), diag::err_thread_unsupported);
64067330f729Sjoerg return;
64077330f729Sjoerg }
64087330f729Sjoerg if (VD->getTSCSpec() != TSCS_unspecified) {
64097330f729Sjoerg S.Diag(AL.getLoc(), diag::err_declspec_thread_on_thread_variable);
64107330f729Sjoerg return;
64117330f729Sjoerg }
64127330f729Sjoerg if (VD->hasLocalStorage()) {
64137330f729Sjoerg S.Diag(AL.getLoc(), diag::err_thread_non_global) << "__declspec(thread)";
64147330f729Sjoerg return;
64157330f729Sjoerg }
64167330f729Sjoerg D->addAttr(::new (S.Context) ThreadAttr(S.Context, AL));
64177330f729Sjoerg }
64187330f729Sjoerg
handleAbiTagAttr(Sema & S,Decl * D,const ParsedAttr & AL)64197330f729Sjoerg static void handleAbiTagAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
64207330f729Sjoerg SmallVector<StringRef, 4> Tags;
64217330f729Sjoerg for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
64227330f729Sjoerg StringRef Tag;
64237330f729Sjoerg if (!S.checkStringLiteralArgumentAttr(AL, I, Tag))
64247330f729Sjoerg return;
64257330f729Sjoerg Tags.push_back(Tag);
64267330f729Sjoerg }
64277330f729Sjoerg
64287330f729Sjoerg if (const auto *NS = dyn_cast<NamespaceDecl>(D)) {
64297330f729Sjoerg if (!NS->isInline()) {
64307330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attr_abi_tag_namespace) << 0;
64317330f729Sjoerg return;
64327330f729Sjoerg }
64337330f729Sjoerg if (NS->isAnonymousNamespace()) {
64347330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attr_abi_tag_namespace) << 1;
64357330f729Sjoerg return;
64367330f729Sjoerg }
64377330f729Sjoerg if (AL.getNumArgs() == 0)
64387330f729Sjoerg Tags.push_back(NS->getName());
6439*e038c9c4Sjoerg } else if (!AL.checkAtLeastNumArgs(S, 1))
64407330f729Sjoerg return;
64417330f729Sjoerg
64427330f729Sjoerg // Store tags sorted and without duplicates.
64437330f729Sjoerg llvm::sort(Tags);
64447330f729Sjoerg Tags.erase(std::unique(Tags.begin(), Tags.end()), Tags.end());
64457330f729Sjoerg
64467330f729Sjoerg D->addAttr(::new (S.Context)
64477330f729Sjoerg AbiTagAttr(S.Context, AL, Tags.data(), Tags.size()));
64487330f729Sjoerg }
64497330f729Sjoerg
handleARMInterruptAttr(Sema & S,Decl * D,const ParsedAttr & AL)64507330f729Sjoerg static void handleARMInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
64517330f729Sjoerg // Check the attribute arguments.
64527330f729Sjoerg if (AL.getNumArgs() > 1) {
64537330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1;
64547330f729Sjoerg return;
64557330f729Sjoerg }
64567330f729Sjoerg
64577330f729Sjoerg StringRef Str;
64587330f729Sjoerg SourceLocation ArgLoc;
64597330f729Sjoerg
64607330f729Sjoerg if (AL.getNumArgs() == 0)
64617330f729Sjoerg Str = "";
64627330f729Sjoerg else if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
64637330f729Sjoerg return;
64647330f729Sjoerg
64657330f729Sjoerg ARMInterruptAttr::InterruptType Kind;
64667330f729Sjoerg if (!ARMInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
64677330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << Str
64687330f729Sjoerg << ArgLoc;
64697330f729Sjoerg return;
64707330f729Sjoerg }
64717330f729Sjoerg
64727330f729Sjoerg D->addAttr(::new (S.Context) ARMInterruptAttr(S.Context, AL, Kind));
64737330f729Sjoerg }
64747330f729Sjoerg
handleMSP430InterruptAttr(Sema & S,Decl * D,const ParsedAttr & AL)64757330f729Sjoerg static void handleMSP430InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
64767330f729Sjoerg // MSP430 'interrupt' attribute is applied to
64777330f729Sjoerg // a function with no parameters and void return type.
64787330f729Sjoerg if (!isFunctionOrMethod(D)) {
64797330f729Sjoerg S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
64807330f729Sjoerg << "'interrupt'" << ExpectedFunctionOrMethod;
64817330f729Sjoerg return;
64827330f729Sjoerg }
64837330f729Sjoerg
64847330f729Sjoerg if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) {
64857330f729Sjoerg S.Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
64867330f729Sjoerg << /*MSP430*/ 1 << 0;
64877330f729Sjoerg return;
64887330f729Sjoerg }
64897330f729Sjoerg
64907330f729Sjoerg if (!getFunctionOrMethodResultType(D)->isVoidType()) {
64917330f729Sjoerg S.Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
64927330f729Sjoerg << /*MSP430*/ 1 << 1;
64937330f729Sjoerg return;
64947330f729Sjoerg }
64957330f729Sjoerg
64967330f729Sjoerg // The attribute takes one integer argument.
6497*e038c9c4Sjoerg if (!AL.checkExactlyNumArgs(S, 1))
64987330f729Sjoerg return;
64997330f729Sjoerg
65007330f729Sjoerg if (!AL.isArgExpr(0)) {
65017330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
65027330f729Sjoerg << AL << AANT_ArgumentIntegerConstant;
65037330f729Sjoerg return;
65047330f729Sjoerg }
65057330f729Sjoerg
65067330f729Sjoerg Expr *NumParamsExpr = static_cast<Expr *>(AL.getArgAsExpr(0));
6507*e038c9c4Sjoerg Optional<llvm::APSInt> NumParams = llvm::APSInt(32);
6508*e038c9c4Sjoerg if (!(NumParams = NumParamsExpr->getIntegerConstantExpr(S.Context))) {
65097330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
65107330f729Sjoerg << AL << AANT_ArgumentIntegerConstant
65117330f729Sjoerg << NumParamsExpr->getSourceRange();
65127330f729Sjoerg return;
65137330f729Sjoerg }
65147330f729Sjoerg // The argument should be in range 0..63.
6515*e038c9c4Sjoerg unsigned Num = NumParams->getLimitedValue(255);
65167330f729Sjoerg if (Num > 63) {
65177330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
6518*e038c9c4Sjoerg << AL << (int)NumParams->getSExtValue()
65197330f729Sjoerg << NumParamsExpr->getSourceRange();
65207330f729Sjoerg return;
65217330f729Sjoerg }
65227330f729Sjoerg
65237330f729Sjoerg D->addAttr(::new (S.Context) MSP430InterruptAttr(S.Context, AL, Num));
65247330f729Sjoerg D->addAttr(UsedAttr::CreateImplicit(S.Context));
65257330f729Sjoerg }
65267330f729Sjoerg
handleMipsInterruptAttr(Sema & S,Decl * D,const ParsedAttr & AL)65277330f729Sjoerg static void handleMipsInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
65287330f729Sjoerg // Only one optional argument permitted.
65297330f729Sjoerg if (AL.getNumArgs() > 1) {
65307330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << AL << 1;
65317330f729Sjoerg return;
65327330f729Sjoerg }
65337330f729Sjoerg
65347330f729Sjoerg StringRef Str;
65357330f729Sjoerg SourceLocation ArgLoc;
65367330f729Sjoerg
65377330f729Sjoerg if (AL.getNumArgs() == 0)
65387330f729Sjoerg Str = "";
65397330f729Sjoerg else if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
65407330f729Sjoerg return;
65417330f729Sjoerg
65427330f729Sjoerg // Semantic checks for a function with the 'interrupt' attribute for MIPS:
65437330f729Sjoerg // a) Must be a function.
65447330f729Sjoerg // b) Must have no parameters.
65457330f729Sjoerg // c) Must have the 'void' return type.
65467330f729Sjoerg // d) Cannot have the 'mips16' attribute, as that instruction set
65477330f729Sjoerg // lacks the 'eret' instruction.
65487330f729Sjoerg // e) The attribute itself must either have no argument or one of the
65497330f729Sjoerg // valid interrupt types, see [MipsInterruptDocs].
65507330f729Sjoerg
65517330f729Sjoerg if (!isFunctionOrMethod(D)) {
65527330f729Sjoerg S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
65537330f729Sjoerg << "'interrupt'" << ExpectedFunctionOrMethod;
65547330f729Sjoerg return;
65557330f729Sjoerg }
65567330f729Sjoerg
65577330f729Sjoerg if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) {
65587330f729Sjoerg S.Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
65597330f729Sjoerg << /*MIPS*/ 0 << 0;
65607330f729Sjoerg return;
65617330f729Sjoerg }
65627330f729Sjoerg
65637330f729Sjoerg if (!getFunctionOrMethodResultType(D)->isVoidType()) {
65647330f729Sjoerg S.Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
65657330f729Sjoerg << /*MIPS*/ 0 << 1;
65667330f729Sjoerg return;
65677330f729Sjoerg }
65687330f729Sjoerg
6569*e038c9c4Sjoerg // We still have to do this manually because the Interrupt attributes are
6570*e038c9c4Sjoerg // a bit special due to sharing their spellings across targets.
65717330f729Sjoerg if (checkAttrMutualExclusion<Mips16Attr>(S, D, AL))
65727330f729Sjoerg return;
65737330f729Sjoerg
65747330f729Sjoerg MipsInterruptAttr::InterruptType Kind;
65757330f729Sjoerg if (!MipsInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
65767330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported)
65777330f729Sjoerg << AL << "'" + std::string(Str) + "'";
65787330f729Sjoerg return;
65797330f729Sjoerg }
65807330f729Sjoerg
65817330f729Sjoerg D->addAttr(::new (S.Context) MipsInterruptAttr(S.Context, AL, Kind));
65827330f729Sjoerg }
65837330f729Sjoerg
handleM68kInterruptAttr(Sema & S,Decl * D,const ParsedAttr & AL)6584*e038c9c4Sjoerg static void handleM68kInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
6585*e038c9c4Sjoerg if (!AL.checkExactlyNumArgs(S, 1))
6586*e038c9c4Sjoerg return;
6587*e038c9c4Sjoerg
6588*e038c9c4Sjoerg if (!AL.isArgExpr(0)) {
6589*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
6590*e038c9c4Sjoerg << AL << AANT_ArgumentIntegerConstant;
6591*e038c9c4Sjoerg return;
6592*e038c9c4Sjoerg }
6593*e038c9c4Sjoerg
6594*e038c9c4Sjoerg // FIXME: Check for decl - it should be void ()(void).
6595*e038c9c4Sjoerg
6596*e038c9c4Sjoerg Expr *NumParamsExpr = static_cast<Expr *>(AL.getArgAsExpr(0));
6597*e038c9c4Sjoerg auto MaybeNumParams = NumParamsExpr->getIntegerConstantExpr(S.Context);
6598*e038c9c4Sjoerg if (!MaybeNumParams) {
6599*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
6600*e038c9c4Sjoerg << AL << AANT_ArgumentIntegerConstant
6601*e038c9c4Sjoerg << NumParamsExpr->getSourceRange();
6602*e038c9c4Sjoerg return;
6603*e038c9c4Sjoerg }
6604*e038c9c4Sjoerg
6605*e038c9c4Sjoerg unsigned Num = MaybeNumParams->getLimitedValue(255);
6606*e038c9c4Sjoerg if ((Num & 1) || Num > 30) {
6607*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
6608*e038c9c4Sjoerg << AL << (int)MaybeNumParams->getSExtValue()
6609*e038c9c4Sjoerg << NumParamsExpr->getSourceRange();
6610*e038c9c4Sjoerg return;
6611*e038c9c4Sjoerg }
6612*e038c9c4Sjoerg
6613*e038c9c4Sjoerg D->addAttr(::new (S.Context) M68kInterruptAttr(S.Context, AL, Num));
6614*e038c9c4Sjoerg D->addAttr(UsedAttr::CreateImplicit(S.Context));
6615*e038c9c4Sjoerg }
6616*e038c9c4Sjoerg
handleAnyX86InterruptAttr(Sema & S,Decl * D,const ParsedAttr & AL)66177330f729Sjoerg static void handleAnyX86InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
66187330f729Sjoerg // Semantic checks for a function with the 'interrupt' attribute.
66197330f729Sjoerg // a) Must be a function.
66207330f729Sjoerg // b) Must have the 'void' return type.
66217330f729Sjoerg // c) Must take 1 or 2 arguments.
66227330f729Sjoerg // d) The 1st argument must be a pointer.
66237330f729Sjoerg // e) The 2nd argument (if any) must be an unsigned integer.
66247330f729Sjoerg if (!isFunctionOrMethod(D) || !hasFunctionProto(D) || isInstanceMethod(D) ||
66257330f729Sjoerg CXXMethodDecl::isStaticOverloadedOperator(
66267330f729Sjoerg cast<NamedDecl>(D)->getDeclName().getCXXOverloadedOperator())) {
66277330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
66287330f729Sjoerg << AL << ExpectedFunctionWithProtoType;
66297330f729Sjoerg return;
66307330f729Sjoerg }
66317330f729Sjoerg // Interrupt handler must have void return type.
66327330f729Sjoerg if (!getFunctionOrMethodResultType(D)->isVoidType()) {
66337330f729Sjoerg S.Diag(getFunctionOrMethodResultSourceRange(D).getBegin(),
66347330f729Sjoerg diag::err_anyx86_interrupt_attribute)
66357330f729Sjoerg << (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86
66367330f729Sjoerg ? 0
66377330f729Sjoerg : 1)
66387330f729Sjoerg << 0;
66397330f729Sjoerg return;
66407330f729Sjoerg }
66417330f729Sjoerg // Interrupt handler must have 1 or 2 parameters.
66427330f729Sjoerg unsigned NumParams = getFunctionOrMethodNumParams(D);
66437330f729Sjoerg if (NumParams < 1 || NumParams > 2) {
66447330f729Sjoerg S.Diag(D->getBeginLoc(), diag::err_anyx86_interrupt_attribute)
66457330f729Sjoerg << (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86
66467330f729Sjoerg ? 0
66477330f729Sjoerg : 1)
66487330f729Sjoerg << 1;
66497330f729Sjoerg return;
66507330f729Sjoerg }
66517330f729Sjoerg // The first argument must be a pointer.
66527330f729Sjoerg if (!getFunctionOrMethodParamType(D, 0)->isPointerType()) {
66537330f729Sjoerg S.Diag(getFunctionOrMethodParamRange(D, 0).getBegin(),
66547330f729Sjoerg diag::err_anyx86_interrupt_attribute)
66557330f729Sjoerg << (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86
66567330f729Sjoerg ? 0
66577330f729Sjoerg : 1)
66587330f729Sjoerg << 2;
66597330f729Sjoerg return;
66607330f729Sjoerg }
66617330f729Sjoerg // The second argument, if present, must be an unsigned integer.
66627330f729Sjoerg unsigned TypeSize =
66637330f729Sjoerg S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86_64
66647330f729Sjoerg ? 64
66657330f729Sjoerg : 32;
66667330f729Sjoerg if (NumParams == 2 &&
66677330f729Sjoerg (!getFunctionOrMethodParamType(D, 1)->isUnsignedIntegerType() ||
66687330f729Sjoerg S.Context.getTypeSize(getFunctionOrMethodParamType(D, 1)) != TypeSize)) {
66697330f729Sjoerg S.Diag(getFunctionOrMethodParamRange(D, 1).getBegin(),
66707330f729Sjoerg diag::err_anyx86_interrupt_attribute)
66717330f729Sjoerg << (S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86
66727330f729Sjoerg ? 0
66737330f729Sjoerg : 1)
66747330f729Sjoerg << 3 << S.Context.getIntTypeForBitwidth(TypeSize, /*Signed=*/false);
66757330f729Sjoerg return;
66767330f729Sjoerg }
66777330f729Sjoerg D->addAttr(::new (S.Context) AnyX86InterruptAttr(S.Context, AL));
66787330f729Sjoerg D->addAttr(UsedAttr::CreateImplicit(S.Context));
66797330f729Sjoerg }
66807330f729Sjoerg
handleAVRInterruptAttr(Sema & S,Decl * D,const ParsedAttr & AL)66817330f729Sjoerg static void handleAVRInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
66827330f729Sjoerg if (!isFunctionOrMethod(D)) {
66837330f729Sjoerg S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
66847330f729Sjoerg << "'interrupt'" << ExpectedFunction;
66857330f729Sjoerg return;
66867330f729Sjoerg }
66877330f729Sjoerg
6688*e038c9c4Sjoerg if (!AL.checkExactlyNumArgs(S, 0))
66897330f729Sjoerg return;
66907330f729Sjoerg
66917330f729Sjoerg handleSimpleAttribute<AVRInterruptAttr>(S, D, AL);
66927330f729Sjoerg }
66937330f729Sjoerg
handleAVRSignalAttr(Sema & S,Decl * D,const ParsedAttr & AL)66947330f729Sjoerg static void handleAVRSignalAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
66957330f729Sjoerg if (!isFunctionOrMethod(D)) {
66967330f729Sjoerg S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
66977330f729Sjoerg << "'signal'" << ExpectedFunction;
66987330f729Sjoerg return;
66997330f729Sjoerg }
67007330f729Sjoerg
6701*e038c9c4Sjoerg if (!AL.checkExactlyNumArgs(S, 0))
67027330f729Sjoerg return;
67037330f729Sjoerg
67047330f729Sjoerg handleSimpleAttribute<AVRSignalAttr>(S, D, AL);
67057330f729Sjoerg }
67067330f729Sjoerg
handleBPFPreserveAIRecord(Sema & S,RecordDecl * RD)6707*e038c9c4Sjoerg static void handleBPFPreserveAIRecord(Sema &S, RecordDecl *RD) {
6708*e038c9c4Sjoerg // Add preserve_access_index attribute to all fields and inner records.
6709*e038c9c4Sjoerg for (auto D : RD->decls()) {
6710*e038c9c4Sjoerg if (D->hasAttr<BPFPreserveAccessIndexAttr>())
6711*e038c9c4Sjoerg continue;
6712*e038c9c4Sjoerg
6713*e038c9c4Sjoerg D->addAttr(BPFPreserveAccessIndexAttr::CreateImplicit(S.Context));
6714*e038c9c4Sjoerg if (auto *Rec = dyn_cast<RecordDecl>(D))
6715*e038c9c4Sjoerg handleBPFPreserveAIRecord(S, Rec);
6716*e038c9c4Sjoerg }
6717*e038c9c4Sjoerg }
6718*e038c9c4Sjoerg
handleBPFPreserveAccessIndexAttr(Sema & S,Decl * D,const ParsedAttr & AL)6719*e038c9c4Sjoerg static void handleBPFPreserveAccessIndexAttr(Sema &S, Decl *D,
6720*e038c9c4Sjoerg const ParsedAttr &AL) {
6721*e038c9c4Sjoerg auto *Rec = cast<RecordDecl>(D);
6722*e038c9c4Sjoerg handleBPFPreserveAIRecord(S, Rec);
6723*e038c9c4Sjoerg Rec->addAttr(::new (S.Context) BPFPreserveAccessIndexAttr(S.Context, AL));
6724*e038c9c4Sjoerg }
6725*e038c9c4Sjoerg
handleWebAssemblyExportNameAttr(Sema & S,Decl * D,const ParsedAttr & AL)6726*e038c9c4Sjoerg static void handleWebAssemblyExportNameAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
67277330f729Sjoerg if (!isFunctionOrMethod(D)) {
67287330f729Sjoerg S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
6729*e038c9c4Sjoerg << "'export_name'" << ExpectedFunction;
67307330f729Sjoerg return;
67317330f729Sjoerg }
67327330f729Sjoerg
67337330f729Sjoerg auto *FD = cast<FunctionDecl>(D);
67347330f729Sjoerg if (FD->isThisDeclarationADefinition()) {
67357330f729Sjoerg S.Diag(D->getLocation(), diag::err_alias_is_definition) << FD << 0;
67367330f729Sjoerg return;
67377330f729Sjoerg }
67387330f729Sjoerg
67397330f729Sjoerg StringRef Str;
67407330f729Sjoerg SourceLocation ArgLoc;
67417330f729Sjoerg if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
67427330f729Sjoerg return;
67437330f729Sjoerg
6744*e038c9c4Sjoerg D->addAttr(::new (S.Context) WebAssemblyExportNameAttr(S.Context, AL, Str));
6745*e038c9c4Sjoerg D->addAttr(UsedAttr::CreateImplicit(S.Context));
6746*e038c9c4Sjoerg }
6747*e038c9c4Sjoerg
6748*e038c9c4Sjoerg WebAssemblyImportModuleAttr *
mergeImportModuleAttr(Decl * D,const WebAssemblyImportModuleAttr & AL)6749*e038c9c4Sjoerg Sema::mergeImportModuleAttr(Decl *D, const WebAssemblyImportModuleAttr &AL) {
6750*e038c9c4Sjoerg auto *FD = cast<FunctionDecl>(D);
6751*e038c9c4Sjoerg
6752*e038c9c4Sjoerg if (const auto *ExistingAttr = FD->getAttr<WebAssemblyImportModuleAttr>()) {
6753*e038c9c4Sjoerg if (ExistingAttr->getImportModule() == AL.getImportModule())
6754*e038c9c4Sjoerg return nullptr;
6755*e038c9c4Sjoerg Diag(ExistingAttr->getLocation(), diag::warn_mismatched_import) << 0
6756*e038c9c4Sjoerg << ExistingAttr->getImportModule() << AL.getImportModule();
6757*e038c9c4Sjoerg Diag(AL.getLoc(), diag::note_previous_attribute);
6758*e038c9c4Sjoerg return nullptr;
6759*e038c9c4Sjoerg }
6760*e038c9c4Sjoerg if (FD->hasBody()) {
6761*e038c9c4Sjoerg Diag(AL.getLoc(), diag::warn_import_on_definition) << 0;
6762*e038c9c4Sjoerg return nullptr;
6763*e038c9c4Sjoerg }
6764*e038c9c4Sjoerg return ::new (Context) WebAssemblyImportModuleAttr(Context, AL,
6765*e038c9c4Sjoerg AL.getImportModule());
6766*e038c9c4Sjoerg }
6767*e038c9c4Sjoerg
6768*e038c9c4Sjoerg WebAssemblyImportNameAttr *
mergeImportNameAttr(Decl * D,const WebAssemblyImportNameAttr & AL)6769*e038c9c4Sjoerg Sema::mergeImportNameAttr(Decl *D, const WebAssemblyImportNameAttr &AL) {
6770*e038c9c4Sjoerg auto *FD = cast<FunctionDecl>(D);
6771*e038c9c4Sjoerg
6772*e038c9c4Sjoerg if (const auto *ExistingAttr = FD->getAttr<WebAssemblyImportNameAttr>()) {
6773*e038c9c4Sjoerg if (ExistingAttr->getImportName() == AL.getImportName())
6774*e038c9c4Sjoerg return nullptr;
6775*e038c9c4Sjoerg Diag(ExistingAttr->getLocation(), diag::warn_mismatched_import) << 1
6776*e038c9c4Sjoerg << ExistingAttr->getImportName() << AL.getImportName();
6777*e038c9c4Sjoerg Diag(AL.getLoc(), diag::note_previous_attribute);
6778*e038c9c4Sjoerg return nullptr;
6779*e038c9c4Sjoerg }
6780*e038c9c4Sjoerg if (FD->hasBody()) {
6781*e038c9c4Sjoerg Diag(AL.getLoc(), diag::warn_import_on_definition) << 1;
6782*e038c9c4Sjoerg return nullptr;
6783*e038c9c4Sjoerg }
6784*e038c9c4Sjoerg return ::new (Context) WebAssemblyImportNameAttr(Context, AL,
6785*e038c9c4Sjoerg AL.getImportName());
6786*e038c9c4Sjoerg }
6787*e038c9c4Sjoerg
6788*e038c9c4Sjoerg static void
handleWebAssemblyImportModuleAttr(Sema & S,Decl * D,const ParsedAttr & AL)6789*e038c9c4Sjoerg handleWebAssemblyImportModuleAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
6790*e038c9c4Sjoerg auto *FD = cast<FunctionDecl>(D);
6791*e038c9c4Sjoerg
6792*e038c9c4Sjoerg StringRef Str;
6793*e038c9c4Sjoerg SourceLocation ArgLoc;
6794*e038c9c4Sjoerg if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
6795*e038c9c4Sjoerg return;
6796*e038c9c4Sjoerg if (FD->hasBody()) {
6797*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::warn_import_on_definition) << 0;
6798*e038c9c4Sjoerg return;
6799*e038c9c4Sjoerg }
6800*e038c9c4Sjoerg
68017330f729Sjoerg FD->addAttr(::new (S.Context)
68027330f729Sjoerg WebAssemblyImportModuleAttr(S.Context, AL, Str));
68037330f729Sjoerg }
68047330f729Sjoerg
6805*e038c9c4Sjoerg static void
handleWebAssemblyImportNameAttr(Sema & S,Decl * D,const ParsedAttr & AL)6806*e038c9c4Sjoerg handleWebAssemblyImportNameAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
68077330f729Sjoerg auto *FD = cast<FunctionDecl>(D);
68087330f729Sjoerg
68097330f729Sjoerg StringRef Str;
68107330f729Sjoerg SourceLocation ArgLoc;
68117330f729Sjoerg if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
68127330f729Sjoerg return;
6813*e038c9c4Sjoerg if (FD->hasBody()) {
6814*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::warn_import_on_definition) << 1;
6815*e038c9c4Sjoerg return;
6816*e038c9c4Sjoerg }
68177330f729Sjoerg
68187330f729Sjoerg FD->addAttr(::new (S.Context) WebAssemblyImportNameAttr(S.Context, AL, Str));
68197330f729Sjoerg }
68207330f729Sjoerg
handleRISCVInterruptAttr(Sema & S,Decl * D,const ParsedAttr & AL)68217330f729Sjoerg static void handleRISCVInterruptAttr(Sema &S, Decl *D,
68227330f729Sjoerg const ParsedAttr &AL) {
68237330f729Sjoerg // Warn about repeated attributes.
68247330f729Sjoerg if (const auto *A = D->getAttr<RISCVInterruptAttr>()) {
68257330f729Sjoerg S.Diag(AL.getRange().getBegin(),
68267330f729Sjoerg diag::warn_riscv_repeated_interrupt_attribute);
68277330f729Sjoerg S.Diag(A->getLocation(), diag::note_riscv_repeated_interrupt_attribute);
68287330f729Sjoerg return;
68297330f729Sjoerg }
68307330f729Sjoerg
68317330f729Sjoerg // Check the attribute argument. Argument is optional.
6832*e038c9c4Sjoerg if (!AL.checkAtMostNumArgs(S, 1))
68337330f729Sjoerg return;
68347330f729Sjoerg
68357330f729Sjoerg StringRef Str;
68367330f729Sjoerg SourceLocation ArgLoc;
68377330f729Sjoerg
68387330f729Sjoerg // 'machine'is the default interrupt mode.
68397330f729Sjoerg if (AL.getNumArgs() == 0)
68407330f729Sjoerg Str = "machine";
68417330f729Sjoerg else if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
68427330f729Sjoerg return;
68437330f729Sjoerg
68447330f729Sjoerg // Semantic checks for a function with the 'interrupt' attribute:
68457330f729Sjoerg // - Must be a function.
68467330f729Sjoerg // - Must have no parameters.
68477330f729Sjoerg // - Must have the 'void' return type.
68487330f729Sjoerg // - The attribute itself must either have no argument or one of the
68497330f729Sjoerg // valid interrupt types, see [RISCVInterruptDocs].
68507330f729Sjoerg
68517330f729Sjoerg if (D->getFunctionType() == nullptr) {
68527330f729Sjoerg S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
68537330f729Sjoerg << "'interrupt'" << ExpectedFunction;
68547330f729Sjoerg return;
68557330f729Sjoerg }
68567330f729Sjoerg
68577330f729Sjoerg if (hasFunctionProto(D) && getFunctionOrMethodNumParams(D) != 0) {
68587330f729Sjoerg S.Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
68597330f729Sjoerg << /*RISC-V*/ 2 << 0;
68607330f729Sjoerg return;
68617330f729Sjoerg }
68627330f729Sjoerg
68637330f729Sjoerg if (!getFunctionOrMethodResultType(D)->isVoidType()) {
68647330f729Sjoerg S.Diag(D->getLocation(), diag::warn_interrupt_attribute_invalid)
68657330f729Sjoerg << /*RISC-V*/ 2 << 1;
68667330f729Sjoerg return;
68677330f729Sjoerg }
68687330f729Sjoerg
68697330f729Sjoerg RISCVInterruptAttr::InterruptType Kind;
68707330f729Sjoerg if (!RISCVInterruptAttr::ConvertStrToInterruptType(Str, Kind)) {
68717330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << Str
68727330f729Sjoerg << ArgLoc;
68737330f729Sjoerg return;
68747330f729Sjoerg }
68757330f729Sjoerg
68767330f729Sjoerg D->addAttr(::new (S.Context) RISCVInterruptAttr(S.Context, AL, Kind));
68777330f729Sjoerg }
68787330f729Sjoerg
handleInterruptAttr(Sema & S,Decl * D,const ParsedAttr & AL)68797330f729Sjoerg static void handleInterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
68807330f729Sjoerg // Dispatch the interrupt attribute based on the current target.
68817330f729Sjoerg switch (S.Context.getTargetInfo().getTriple().getArch()) {
68827330f729Sjoerg case llvm::Triple::msp430:
68837330f729Sjoerg handleMSP430InterruptAttr(S, D, AL);
68847330f729Sjoerg break;
68857330f729Sjoerg case llvm::Triple::mipsel:
68867330f729Sjoerg case llvm::Triple::mips:
68877330f729Sjoerg handleMipsInterruptAttr(S, D, AL);
68887330f729Sjoerg break;
6889*e038c9c4Sjoerg case llvm::Triple::m68k:
6890*e038c9c4Sjoerg handleM68kInterruptAttr(S, D, AL);
6891*e038c9c4Sjoerg break;
68927330f729Sjoerg case llvm::Triple::x86:
68937330f729Sjoerg case llvm::Triple::x86_64:
68947330f729Sjoerg handleAnyX86InterruptAttr(S, D, AL);
68957330f729Sjoerg break;
68967330f729Sjoerg case llvm::Triple::avr:
68977330f729Sjoerg handleAVRInterruptAttr(S, D, AL);
68987330f729Sjoerg break;
68997330f729Sjoerg case llvm::Triple::riscv32:
69007330f729Sjoerg case llvm::Triple::riscv64:
69017330f729Sjoerg handleRISCVInterruptAttr(S, D, AL);
69027330f729Sjoerg break;
69037330f729Sjoerg default:
69047330f729Sjoerg handleARMInterruptAttr(S, D, AL);
69057330f729Sjoerg break;
69067330f729Sjoerg }
69077330f729Sjoerg }
69087330f729Sjoerg
69097330f729Sjoerg static bool
checkAMDGPUFlatWorkGroupSizeArguments(Sema & S,Expr * MinExpr,Expr * MaxExpr,const AMDGPUFlatWorkGroupSizeAttr & Attr)69107330f729Sjoerg checkAMDGPUFlatWorkGroupSizeArguments(Sema &S, Expr *MinExpr, Expr *MaxExpr,
69117330f729Sjoerg const AMDGPUFlatWorkGroupSizeAttr &Attr) {
69127330f729Sjoerg // Accept template arguments for now as they depend on something else.
69137330f729Sjoerg // We'll get to check them when they eventually get instantiated.
69147330f729Sjoerg if (MinExpr->isValueDependent() || MaxExpr->isValueDependent())
69157330f729Sjoerg return false;
69167330f729Sjoerg
69177330f729Sjoerg uint32_t Min = 0;
69187330f729Sjoerg if (!checkUInt32Argument(S, Attr, MinExpr, Min, 0))
69197330f729Sjoerg return true;
69207330f729Sjoerg
69217330f729Sjoerg uint32_t Max = 0;
69227330f729Sjoerg if (!checkUInt32Argument(S, Attr, MaxExpr, Max, 1))
69237330f729Sjoerg return true;
69247330f729Sjoerg
69257330f729Sjoerg if (Min == 0 && Max != 0) {
69267330f729Sjoerg S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
69277330f729Sjoerg << &Attr << 0;
69287330f729Sjoerg return true;
69297330f729Sjoerg }
69307330f729Sjoerg if (Min > Max) {
69317330f729Sjoerg S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
69327330f729Sjoerg << &Attr << 1;
69337330f729Sjoerg return true;
69347330f729Sjoerg }
69357330f729Sjoerg
69367330f729Sjoerg return false;
69377330f729Sjoerg }
69387330f729Sjoerg
addAMDGPUFlatWorkGroupSizeAttr(Decl * D,const AttributeCommonInfo & CI,Expr * MinExpr,Expr * MaxExpr)69397330f729Sjoerg void Sema::addAMDGPUFlatWorkGroupSizeAttr(Decl *D,
69407330f729Sjoerg const AttributeCommonInfo &CI,
69417330f729Sjoerg Expr *MinExpr, Expr *MaxExpr) {
69427330f729Sjoerg AMDGPUFlatWorkGroupSizeAttr TmpAttr(Context, CI, MinExpr, MaxExpr);
69437330f729Sjoerg
69447330f729Sjoerg if (checkAMDGPUFlatWorkGroupSizeArguments(*this, MinExpr, MaxExpr, TmpAttr))
69457330f729Sjoerg return;
69467330f729Sjoerg
69477330f729Sjoerg D->addAttr(::new (Context)
69487330f729Sjoerg AMDGPUFlatWorkGroupSizeAttr(Context, CI, MinExpr, MaxExpr));
69497330f729Sjoerg }
69507330f729Sjoerg
handleAMDGPUFlatWorkGroupSizeAttr(Sema & S,Decl * D,const ParsedAttr & AL)69517330f729Sjoerg static void handleAMDGPUFlatWorkGroupSizeAttr(Sema &S, Decl *D,
69527330f729Sjoerg const ParsedAttr &AL) {
69537330f729Sjoerg Expr *MinExpr = AL.getArgAsExpr(0);
69547330f729Sjoerg Expr *MaxExpr = AL.getArgAsExpr(1);
69557330f729Sjoerg
69567330f729Sjoerg S.addAMDGPUFlatWorkGroupSizeAttr(D, AL, MinExpr, MaxExpr);
69577330f729Sjoerg }
69587330f729Sjoerg
checkAMDGPUWavesPerEUArguments(Sema & S,Expr * MinExpr,Expr * MaxExpr,const AMDGPUWavesPerEUAttr & Attr)69597330f729Sjoerg static bool checkAMDGPUWavesPerEUArguments(Sema &S, Expr *MinExpr,
69607330f729Sjoerg Expr *MaxExpr,
69617330f729Sjoerg const AMDGPUWavesPerEUAttr &Attr) {
69627330f729Sjoerg if (S.DiagnoseUnexpandedParameterPack(MinExpr) ||
69637330f729Sjoerg (MaxExpr && S.DiagnoseUnexpandedParameterPack(MaxExpr)))
69647330f729Sjoerg return true;
69657330f729Sjoerg
69667330f729Sjoerg // Accept template arguments for now as they depend on something else.
69677330f729Sjoerg // We'll get to check them when they eventually get instantiated.
69687330f729Sjoerg if (MinExpr->isValueDependent() || (MaxExpr && MaxExpr->isValueDependent()))
69697330f729Sjoerg return false;
69707330f729Sjoerg
69717330f729Sjoerg uint32_t Min = 0;
69727330f729Sjoerg if (!checkUInt32Argument(S, Attr, MinExpr, Min, 0))
69737330f729Sjoerg return true;
69747330f729Sjoerg
69757330f729Sjoerg uint32_t Max = 0;
69767330f729Sjoerg if (MaxExpr && !checkUInt32Argument(S, Attr, MaxExpr, Max, 1))
69777330f729Sjoerg return true;
69787330f729Sjoerg
69797330f729Sjoerg if (Min == 0 && Max != 0) {
69807330f729Sjoerg S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
69817330f729Sjoerg << &Attr << 0;
69827330f729Sjoerg return true;
69837330f729Sjoerg }
69847330f729Sjoerg if (Max != 0 && Min > Max) {
69857330f729Sjoerg S.Diag(Attr.getLocation(), diag::err_attribute_argument_invalid)
69867330f729Sjoerg << &Attr << 1;
69877330f729Sjoerg return true;
69887330f729Sjoerg }
69897330f729Sjoerg
69907330f729Sjoerg return false;
69917330f729Sjoerg }
69927330f729Sjoerg
addAMDGPUWavesPerEUAttr(Decl * D,const AttributeCommonInfo & CI,Expr * MinExpr,Expr * MaxExpr)69937330f729Sjoerg void Sema::addAMDGPUWavesPerEUAttr(Decl *D, const AttributeCommonInfo &CI,
69947330f729Sjoerg Expr *MinExpr, Expr *MaxExpr) {
69957330f729Sjoerg AMDGPUWavesPerEUAttr TmpAttr(Context, CI, MinExpr, MaxExpr);
69967330f729Sjoerg
69977330f729Sjoerg if (checkAMDGPUWavesPerEUArguments(*this, MinExpr, MaxExpr, TmpAttr))
69987330f729Sjoerg return;
69997330f729Sjoerg
70007330f729Sjoerg D->addAttr(::new (Context)
70017330f729Sjoerg AMDGPUWavesPerEUAttr(Context, CI, MinExpr, MaxExpr));
70027330f729Sjoerg }
70037330f729Sjoerg
handleAMDGPUWavesPerEUAttr(Sema & S,Decl * D,const ParsedAttr & AL)70047330f729Sjoerg static void handleAMDGPUWavesPerEUAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
7005*e038c9c4Sjoerg if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 2))
70067330f729Sjoerg return;
70077330f729Sjoerg
70087330f729Sjoerg Expr *MinExpr = AL.getArgAsExpr(0);
70097330f729Sjoerg Expr *MaxExpr = (AL.getNumArgs() > 1) ? AL.getArgAsExpr(1) : nullptr;
70107330f729Sjoerg
70117330f729Sjoerg S.addAMDGPUWavesPerEUAttr(D, AL, MinExpr, MaxExpr);
70127330f729Sjoerg }
70137330f729Sjoerg
handleAMDGPUNumSGPRAttr(Sema & S,Decl * D,const ParsedAttr & AL)70147330f729Sjoerg static void handleAMDGPUNumSGPRAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
70157330f729Sjoerg uint32_t NumSGPR = 0;
70167330f729Sjoerg Expr *NumSGPRExpr = AL.getArgAsExpr(0);
70177330f729Sjoerg if (!checkUInt32Argument(S, AL, NumSGPRExpr, NumSGPR))
70187330f729Sjoerg return;
70197330f729Sjoerg
70207330f729Sjoerg D->addAttr(::new (S.Context) AMDGPUNumSGPRAttr(S.Context, AL, NumSGPR));
70217330f729Sjoerg }
70227330f729Sjoerg
handleAMDGPUNumVGPRAttr(Sema & S,Decl * D,const ParsedAttr & AL)70237330f729Sjoerg static void handleAMDGPUNumVGPRAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
70247330f729Sjoerg uint32_t NumVGPR = 0;
70257330f729Sjoerg Expr *NumVGPRExpr = AL.getArgAsExpr(0);
70267330f729Sjoerg if (!checkUInt32Argument(S, AL, NumVGPRExpr, NumVGPR))
70277330f729Sjoerg return;
70287330f729Sjoerg
70297330f729Sjoerg D->addAttr(::new (S.Context) AMDGPUNumVGPRAttr(S.Context, AL, NumVGPR));
70307330f729Sjoerg }
70317330f729Sjoerg
handleX86ForceAlignArgPointerAttr(Sema & S,Decl * D,const ParsedAttr & AL)70327330f729Sjoerg static void handleX86ForceAlignArgPointerAttr(Sema &S, Decl *D,
70337330f729Sjoerg const ParsedAttr &AL) {
70347330f729Sjoerg // If we try to apply it to a function pointer, don't warn, but don't
70357330f729Sjoerg // do anything, either. It doesn't matter anyway, because there's nothing
70367330f729Sjoerg // special about calling a force_align_arg_pointer function.
70377330f729Sjoerg const auto *VD = dyn_cast<ValueDecl>(D);
70387330f729Sjoerg if (VD && VD->getType()->isFunctionPointerType())
70397330f729Sjoerg return;
70407330f729Sjoerg // Also don't warn on function pointer typedefs.
70417330f729Sjoerg const auto *TD = dyn_cast<TypedefNameDecl>(D);
70427330f729Sjoerg if (TD && (TD->getUnderlyingType()->isFunctionPointerType() ||
70437330f729Sjoerg TD->getUnderlyingType()->isFunctionType()))
70447330f729Sjoerg return;
70457330f729Sjoerg // Attribute can only be applied to function types.
70467330f729Sjoerg if (!isa<FunctionDecl>(D)) {
70477330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
70487330f729Sjoerg << AL << ExpectedFunction;
70497330f729Sjoerg return;
70507330f729Sjoerg }
70517330f729Sjoerg
70527330f729Sjoerg D->addAttr(::new (S.Context) X86ForceAlignArgPointerAttr(S.Context, AL));
70537330f729Sjoerg }
70547330f729Sjoerg
handleLayoutVersion(Sema & S,Decl * D,const ParsedAttr & AL)70557330f729Sjoerg static void handleLayoutVersion(Sema &S, Decl *D, const ParsedAttr &AL) {
70567330f729Sjoerg uint32_t Version;
70577330f729Sjoerg Expr *VersionExpr = static_cast<Expr *>(AL.getArgAsExpr(0));
70587330f729Sjoerg if (!checkUInt32Argument(S, AL, AL.getArgAsExpr(0), Version))
70597330f729Sjoerg return;
70607330f729Sjoerg
70617330f729Sjoerg // TODO: Investigate what happens with the next major version of MSVC.
70627330f729Sjoerg if (Version != LangOptions::MSVC2015 / 100) {
70637330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
70647330f729Sjoerg << AL << Version << VersionExpr->getSourceRange();
70657330f729Sjoerg return;
70667330f729Sjoerg }
70677330f729Sjoerg
70687330f729Sjoerg // The attribute expects a "major" version number like 19, but new versions of
70697330f729Sjoerg // MSVC have moved to updating the "minor", or less significant numbers, so we
70707330f729Sjoerg // have to multiply by 100 now.
70717330f729Sjoerg Version *= 100;
70727330f729Sjoerg
70737330f729Sjoerg D->addAttr(::new (S.Context) LayoutVersionAttr(S.Context, AL, Version));
70747330f729Sjoerg }
70757330f729Sjoerg
mergeDLLImportAttr(Decl * D,const AttributeCommonInfo & CI)70767330f729Sjoerg DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D,
70777330f729Sjoerg const AttributeCommonInfo &CI) {
70787330f729Sjoerg if (D->hasAttr<DLLExportAttr>()) {
70797330f729Sjoerg Diag(CI.getLoc(), diag::warn_attribute_ignored) << "'dllimport'";
70807330f729Sjoerg return nullptr;
70817330f729Sjoerg }
70827330f729Sjoerg
70837330f729Sjoerg if (D->hasAttr<DLLImportAttr>())
70847330f729Sjoerg return nullptr;
70857330f729Sjoerg
70867330f729Sjoerg return ::new (Context) DLLImportAttr(Context, CI);
70877330f729Sjoerg }
70887330f729Sjoerg
mergeDLLExportAttr(Decl * D,const AttributeCommonInfo & CI)70897330f729Sjoerg DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D,
70907330f729Sjoerg const AttributeCommonInfo &CI) {
70917330f729Sjoerg if (DLLImportAttr *Import = D->getAttr<DLLImportAttr>()) {
70927330f729Sjoerg Diag(Import->getLocation(), diag::warn_attribute_ignored) << Import;
70937330f729Sjoerg D->dropAttr<DLLImportAttr>();
70947330f729Sjoerg }
70957330f729Sjoerg
70967330f729Sjoerg if (D->hasAttr<DLLExportAttr>())
70977330f729Sjoerg return nullptr;
70987330f729Sjoerg
70997330f729Sjoerg return ::new (Context) DLLExportAttr(Context, CI);
71007330f729Sjoerg }
71017330f729Sjoerg
handleDLLAttr(Sema & S,Decl * D,const ParsedAttr & A)71027330f729Sjoerg static void handleDLLAttr(Sema &S, Decl *D, const ParsedAttr &A) {
71037330f729Sjoerg if (isa<ClassTemplatePartialSpecializationDecl>(D) &&
7104*e038c9c4Sjoerg (S.Context.getTargetInfo().shouldDLLImportComdatSymbols())) {
71057330f729Sjoerg S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored) << A;
71067330f729Sjoerg return;
71077330f729Sjoerg }
71087330f729Sjoerg
71097330f729Sjoerg if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
71107330f729Sjoerg if (FD->isInlined() && A.getKind() == ParsedAttr::AT_DLLImport &&
7111*e038c9c4Sjoerg !(S.Context.getTargetInfo().shouldDLLImportComdatSymbols())) {
71127330f729Sjoerg // MinGW doesn't allow dllimport on inline functions.
71137330f729Sjoerg S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored_on_inline)
71147330f729Sjoerg << A;
71157330f729Sjoerg return;
71167330f729Sjoerg }
71177330f729Sjoerg }
71187330f729Sjoerg
71197330f729Sjoerg if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
7120*e038c9c4Sjoerg if ((S.Context.getTargetInfo().shouldDLLImportComdatSymbols()) &&
71217330f729Sjoerg MD->getParent()->isLambda()) {
71227330f729Sjoerg S.Diag(A.getRange().getBegin(), diag::err_attribute_dll_lambda) << A;
71237330f729Sjoerg return;
71247330f729Sjoerg }
71257330f729Sjoerg }
71267330f729Sjoerg
71277330f729Sjoerg Attr *NewAttr = A.getKind() == ParsedAttr::AT_DLLExport
71287330f729Sjoerg ? (Attr *)S.mergeDLLExportAttr(D, A)
71297330f729Sjoerg : (Attr *)S.mergeDLLImportAttr(D, A);
71307330f729Sjoerg if (NewAttr)
71317330f729Sjoerg D->addAttr(NewAttr);
71327330f729Sjoerg }
71337330f729Sjoerg
71347330f729Sjoerg MSInheritanceAttr *
mergeMSInheritanceAttr(Decl * D,const AttributeCommonInfo & CI,bool BestCase,MSInheritanceModel Model)71357330f729Sjoerg Sema::mergeMSInheritanceAttr(Decl *D, const AttributeCommonInfo &CI,
71367330f729Sjoerg bool BestCase,
7137*e038c9c4Sjoerg MSInheritanceModel Model) {
71387330f729Sjoerg if (MSInheritanceAttr *IA = D->getAttr<MSInheritanceAttr>()) {
7139*e038c9c4Sjoerg if (IA->getInheritanceModel() == Model)
71407330f729Sjoerg return nullptr;
71417330f729Sjoerg Diag(IA->getLocation(), diag::err_mismatched_ms_inheritance)
71427330f729Sjoerg << 1 /*previous declaration*/;
71437330f729Sjoerg Diag(CI.getLoc(), diag::note_previous_ms_inheritance);
71447330f729Sjoerg D->dropAttr<MSInheritanceAttr>();
71457330f729Sjoerg }
71467330f729Sjoerg
71477330f729Sjoerg auto *RD = cast<CXXRecordDecl>(D);
71487330f729Sjoerg if (RD->hasDefinition()) {
71497330f729Sjoerg if (checkMSInheritanceAttrOnDefinition(RD, CI.getRange(), BestCase,
7150*e038c9c4Sjoerg Model)) {
71517330f729Sjoerg return nullptr;
71527330f729Sjoerg }
71537330f729Sjoerg } else {
71547330f729Sjoerg if (isa<ClassTemplatePartialSpecializationDecl>(RD)) {
71557330f729Sjoerg Diag(CI.getLoc(), diag::warn_ignored_ms_inheritance)
71567330f729Sjoerg << 1 /*partial specialization*/;
71577330f729Sjoerg return nullptr;
71587330f729Sjoerg }
71597330f729Sjoerg if (RD->getDescribedClassTemplate()) {
71607330f729Sjoerg Diag(CI.getLoc(), diag::warn_ignored_ms_inheritance)
71617330f729Sjoerg << 0 /*primary template*/;
71627330f729Sjoerg return nullptr;
71637330f729Sjoerg }
71647330f729Sjoerg }
71657330f729Sjoerg
71667330f729Sjoerg return ::new (Context) MSInheritanceAttr(Context, CI, BestCase);
71677330f729Sjoerg }
71687330f729Sjoerg
handleCapabilityAttr(Sema & S,Decl * D,const ParsedAttr & AL)71697330f729Sjoerg static void handleCapabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
71707330f729Sjoerg // The capability attributes take a single string parameter for the name of
71717330f729Sjoerg // the capability they represent. The lockable attribute does not take any
71727330f729Sjoerg // parameters. However, semantically, both attributes represent the same
71737330f729Sjoerg // concept, and so they use the same semantic attribute. Eventually, the
71747330f729Sjoerg // lockable attribute will be removed.
71757330f729Sjoerg //
71767330f729Sjoerg // For backward compatibility, any capability which has no specified string
71777330f729Sjoerg // literal will be considered a "mutex."
71787330f729Sjoerg StringRef N("mutex");
71797330f729Sjoerg SourceLocation LiteralLoc;
71807330f729Sjoerg if (AL.getKind() == ParsedAttr::AT_Capability &&
71817330f729Sjoerg !S.checkStringLiteralArgumentAttr(AL, 0, N, &LiteralLoc))
71827330f729Sjoerg return;
71837330f729Sjoerg
71847330f729Sjoerg D->addAttr(::new (S.Context) CapabilityAttr(S.Context, AL, N));
71857330f729Sjoerg }
71867330f729Sjoerg
handleAssertCapabilityAttr(Sema & S,Decl * D,const ParsedAttr & AL)71877330f729Sjoerg static void handleAssertCapabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
71887330f729Sjoerg SmallVector<Expr*, 1> Args;
71897330f729Sjoerg if (!checkLockFunAttrCommon(S, D, AL, Args))
71907330f729Sjoerg return;
71917330f729Sjoerg
71927330f729Sjoerg D->addAttr(::new (S.Context)
71937330f729Sjoerg AssertCapabilityAttr(S.Context, AL, Args.data(), Args.size()));
71947330f729Sjoerg }
71957330f729Sjoerg
handleAcquireCapabilityAttr(Sema & S,Decl * D,const ParsedAttr & AL)71967330f729Sjoerg static void handleAcquireCapabilityAttr(Sema &S, Decl *D,
71977330f729Sjoerg const ParsedAttr &AL) {
71987330f729Sjoerg SmallVector<Expr*, 1> Args;
71997330f729Sjoerg if (!checkLockFunAttrCommon(S, D, AL, Args))
72007330f729Sjoerg return;
72017330f729Sjoerg
72027330f729Sjoerg D->addAttr(::new (S.Context) AcquireCapabilityAttr(S.Context, AL, Args.data(),
72037330f729Sjoerg Args.size()));
72047330f729Sjoerg }
72057330f729Sjoerg
handleTryAcquireCapabilityAttr(Sema & S,Decl * D,const ParsedAttr & AL)72067330f729Sjoerg static void handleTryAcquireCapabilityAttr(Sema &S, Decl *D,
72077330f729Sjoerg const ParsedAttr &AL) {
72087330f729Sjoerg SmallVector<Expr*, 2> Args;
72097330f729Sjoerg if (!checkTryLockFunAttrCommon(S, D, AL, Args))
72107330f729Sjoerg return;
72117330f729Sjoerg
72127330f729Sjoerg D->addAttr(::new (S.Context) TryAcquireCapabilityAttr(
72137330f729Sjoerg S.Context, AL, AL.getArgAsExpr(0), Args.data(), Args.size()));
72147330f729Sjoerg }
72157330f729Sjoerg
handleReleaseCapabilityAttr(Sema & S,Decl * D,const ParsedAttr & AL)72167330f729Sjoerg static void handleReleaseCapabilityAttr(Sema &S, Decl *D,
72177330f729Sjoerg const ParsedAttr &AL) {
72187330f729Sjoerg // Check that all arguments are lockable objects.
72197330f729Sjoerg SmallVector<Expr *, 1> Args;
72207330f729Sjoerg checkAttrArgsAreCapabilityObjs(S, D, AL, Args, 0, true);
72217330f729Sjoerg
72227330f729Sjoerg D->addAttr(::new (S.Context) ReleaseCapabilityAttr(S.Context, AL, Args.data(),
72237330f729Sjoerg Args.size()));
72247330f729Sjoerg }
72257330f729Sjoerg
handleRequiresCapabilityAttr(Sema & S,Decl * D,const ParsedAttr & AL)72267330f729Sjoerg static void handleRequiresCapabilityAttr(Sema &S, Decl *D,
72277330f729Sjoerg const ParsedAttr &AL) {
7228*e038c9c4Sjoerg if (!AL.checkAtLeastNumArgs(S, 1))
72297330f729Sjoerg return;
72307330f729Sjoerg
72317330f729Sjoerg // check that all arguments are lockable objects
72327330f729Sjoerg SmallVector<Expr*, 1> Args;
72337330f729Sjoerg checkAttrArgsAreCapabilityObjs(S, D, AL, Args);
72347330f729Sjoerg if (Args.empty())
72357330f729Sjoerg return;
72367330f729Sjoerg
72377330f729Sjoerg RequiresCapabilityAttr *RCA = ::new (S.Context)
72387330f729Sjoerg RequiresCapabilityAttr(S.Context, AL, Args.data(), Args.size());
72397330f729Sjoerg
72407330f729Sjoerg D->addAttr(RCA);
72417330f729Sjoerg }
72427330f729Sjoerg
handleDeprecatedAttr(Sema & S,Decl * D,const ParsedAttr & AL)72437330f729Sjoerg static void handleDeprecatedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
72447330f729Sjoerg if (const auto *NSD = dyn_cast<NamespaceDecl>(D)) {
72457330f729Sjoerg if (NSD->isAnonymousNamespace()) {
72467330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_deprecated_anonymous_namespace);
72477330f729Sjoerg // Do not want to attach the attribute to the namespace because that will
72487330f729Sjoerg // cause confusing diagnostic reports for uses of declarations within the
72497330f729Sjoerg // namespace.
72507330f729Sjoerg return;
72517330f729Sjoerg }
72527330f729Sjoerg }
72537330f729Sjoerg
72547330f729Sjoerg // Handle the cases where the attribute has a text message.
72557330f729Sjoerg StringRef Str, Replacement;
72567330f729Sjoerg if (AL.isArgExpr(0) && AL.getArgAsExpr(0) &&
72577330f729Sjoerg !S.checkStringLiteralArgumentAttr(AL, 0, Str))
72587330f729Sjoerg return;
72597330f729Sjoerg
72607330f729Sjoerg // Only support a single optional message for Declspec and CXX11.
72617330f729Sjoerg if (AL.isDeclspecAttribute() || AL.isCXX11Attribute())
7262*e038c9c4Sjoerg AL.checkAtMostNumArgs(S, 1);
72637330f729Sjoerg else if (AL.isArgExpr(1) && AL.getArgAsExpr(1) &&
72647330f729Sjoerg !S.checkStringLiteralArgumentAttr(AL, 1, Replacement))
72657330f729Sjoerg return;
72667330f729Sjoerg
72677330f729Sjoerg if (!S.getLangOpts().CPlusPlus14 && AL.isCXX11Attribute() && !AL.isGNUScope())
72687330f729Sjoerg S.Diag(AL.getLoc(), diag::ext_cxx14_attr) << AL;
72697330f729Sjoerg
72707330f729Sjoerg D->addAttr(::new (S.Context) DeprecatedAttr(S.Context, AL, Str, Replacement));
72717330f729Sjoerg }
72727330f729Sjoerg
isGlobalVar(const Decl * D)72737330f729Sjoerg static bool isGlobalVar(const Decl *D) {
72747330f729Sjoerg if (const auto *S = dyn_cast<VarDecl>(D))
72757330f729Sjoerg return S->hasGlobalStorage();
72767330f729Sjoerg return false;
72777330f729Sjoerg }
72787330f729Sjoerg
handleNoSanitizeAttr(Sema & S,Decl * D,const ParsedAttr & AL)72797330f729Sjoerg static void handleNoSanitizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
7280*e038c9c4Sjoerg if (!AL.checkAtLeastNumArgs(S, 1))
72817330f729Sjoerg return;
72827330f729Sjoerg
72837330f729Sjoerg std::vector<StringRef> Sanitizers;
72847330f729Sjoerg
72857330f729Sjoerg for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
72867330f729Sjoerg StringRef SanitizerName;
72877330f729Sjoerg SourceLocation LiteralLoc;
72887330f729Sjoerg
72897330f729Sjoerg if (!S.checkStringLiteralArgumentAttr(AL, I, SanitizerName, &LiteralLoc))
72907330f729Sjoerg return;
72917330f729Sjoerg
72927330f729Sjoerg if (parseSanitizerValue(SanitizerName, /*AllowGroups=*/true) ==
72937330f729Sjoerg SanitizerMask())
72947330f729Sjoerg S.Diag(LiteralLoc, diag::warn_unknown_sanitizer_ignored) << SanitizerName;
72957330f729Sjoerg else if (isGlobalVar(D) && SanitizerName != "address")
72967330f729Sjoerg S.Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
72977330f729Sjoerg << AL << ExpectedFunctionOrMethod;
72987330f729Sjoerg Sanitizers.push_back(SanitizerName);
72997330f729Sjoerg }
73007330f729Sjoerg
73017330f729Sjoerg D->addAttr(::new (S.Context) NoSanitizeAttr(S.Context, AL, Sanitizers.data(),
73027330f729Sjoerg Sanitizers.size()));
73037330f729Sjoerg }
73047330f729Sjoerg
handleNoSanitizeSpecificAttr(Sema & S,Decl * D,const ParsedAttr & AL)73057330f729Sjoerg static void handleNoSanitizeSpecificAttr(Sema &S, Decl *D,
73067330f729Sjoerg const ParsedAttr &AL) {
73077330f729Sjoerg StringRef AttrName = AL.getAttrName()->getName();
73087330f729Sjoerg normalizeName(AttrName);
73097330f729Sjoerg StringRef SanitizerName = llvm::StringSwitch<StringRef>(AttrName)
73107330f729Sjoerg .Case("no_address_safety_analysis", "address")
73117330f729Sjoerg .Case("no_sanitize_address", "address")
73127330f729Sjoerg .Case("no_sanitize_thread", "thread")
73137330f729Sjoerg .Case("no_sanitize_memory", "memory");
73147330f729Sjoerg if (isGlobalVar(D) && SanitizerName != "address")
73157330f729Sjoerg S.Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
73167330f729Sjoerg << AL << ExpectedFunction;
73177330f729Sjoerg
73187330f729Sjoerg // FIXME: Rather than create a NoSanitizeSpecificAttr, this creates a
73197330f729Sjoerg // NoSanitizeAttr object; but we need to calculate the correct spelling list
73207330f729Sjoerg // index rather than incorrectly assume the index for NoSanitizeSpecificAttr
73217330f729Sjoerg // has the same spellings as the index for NoSanitizeAttr. We don't have a
73227330f729Sjoerg // general way to "translate" between the two, so this hack attempts to work
73237330f729Sjoerg // around the issue with hard-coded indicies. This is critical for calling
73247330f729Sjoerg // getSpelling() or prettyPrint() on the resulting semantic attribute object
73257330f729Sjoerg // without failing assertions.
73267330f729Sjoerg unsigned TranslatedSpellingIndex = 0;
73277330f729Sjoerg if (AL.isC2xAttribute() || AL.isCXX11Attribute())
73287330f729Sjoerg TranslatedSpellingIndex = 1;
73297330f729Sjoerg
73307330f729Sjoerg AttributeCommonInfo Info = AL;
73317330f729Sjoerg Info.setAttributeSpellingListIndex(TranslatedSpellingIndex);
73327330f729Sjoerg D->addAttr(::new (S.Context)
73337330f729Sjoerg NoSanitizeAttr(S.Context, Info, &SanitizerName, 1));
73347330f729Sjoerg }
73357330f729Sjoerg
handleInternalLinkageAttr(Sema & S,Decl * D,const ParsedAttr & AL)73367330f729Sjoerg static void handleInternalLinkageAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
73377330f729Sjoerg if (InternalLinkageAttr *Internal = S.mergeInternalLinkageAttr(D, AL))
73387330f729Sjoerg D->addAttr(Internal);
73397330f729Sjoerg }
73407330f729Sjoerg
handleOpenCLNoSVMAttr(Sema & S,Decl * D,const ParsedAttr & AL)73417330f729Sjoerg static void handleOpenCLNoSVMAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
73427330f729Sjoerg if (S.LangOpts.OpenCLVersion != 200)
73437330f729Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_requires_opencl_version)
73447330f729Sjoerg << AL << "2.0" << 0;
73457330f729Sjoerg else
73467330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_opencl_attr_deprecated_ignored) << AL
73477330f729Sjoerg << "2.0";
73487330f729Sjoerg }
73497330f729Sjoerg
handleOpenCLAccessAttr(Sema & S,Decl * D,const ParsedAttr & AL)73507330f729Sjoerg static void handleOpenCLAccessAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
73517330f729Sjoerg if (D->isInvalidDecl())
73527330f729Sjoerg return;
73537330f729Sjoerg
73547330f729Sjoerg // Check if there is only one access qualifier.
73557330f729Sjoerg if (D->hasAttr<OpenCLAccessAttr>()) {
73567330f729Sjoerg if (D->getAttr<OpenCLAccessAttr>()->getSemanticSpelling() ==
73577330f729Sjoerg AL.getSemanticSpelling()) {
73587330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_duplicate_declspec)
73597330f729Sjoerg << AL.getAttrName()->getName() << AL.getRange();
73607330f729Sjoerg } else {
73617330f729Sjoerg S.Diag(AL.getLoc(), diag::err_opencl_multiple_access_qualifiers)
73627330f729Sjoerg << D->getSourceRange();
73637330f729Sjoerg D->setInvalidDecl(true);
73647330f729Sjoerg return;
73657330f729Sjoerg }
73667330f729Sjoerg }
73677330f729Sjoerg
73687330f729Sjoerg // OpenCL v2.0 s6.6 - read_write can be used for image types to specify that an
73697330f729Sjoerg // image object can be read and written.
73707330f729Sjoerg // OpenCL v2.0 s6.13.6 - A kernel cannot read from and write to the same pipe
73717330f729Sjoerg // object. Using the read_write (or __read_write) qualifier with the pipe
73727330f729Sjoerg // qualifier is a compilation error.
73737330f729Sjoerg if (const auto *PDecl = dyn_cast<ParmVarDecl>(D)) {
73747330f729Sjoerg const Type *DeclTy = PDecl->getType().getCanonicalType().getTypePtr();
73757330f729Sjoerg if (AL.getAttrName()->getName().find("read_write") != StringRef::npos) {
73767330f729Sjoerg if ((!S.getLangOpts().OpenCLCPlusPlus &&
73777330f729Sjoerg S.getLangOpts().OpenCLVersion < 200) ||
73787330f729Sjoerg DeclTy->isPipeType()) {
73797330f729Sjoerg S.Diag(AL.getLoc(), diag::err_opencl_invalid_read_write)
73807330f729Sjoerg << AL << PDecl->getType() << DeclTy->isImageType();
73817330f729Sjoerg D->setInvalidDecl(true);
73827330f729Sjoerg return;
73837330f729Sjoerg }
73847330f729Sjoerg }
73857330f729Sjoerg }
73867330f729Sjoerg
73877330f729Sjoerg D->addAttr(::new (S.Context) OpenCLAccessAttr(S.Context, AL));
73887330f729Sjoerg }
73897330f729Sjoerg
handleSYCLKernelAttr(Sema & S,Decl * D,const ParsedAttr & AL)7390*e038c9c4Sjoerg static void handleSYCLKernelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
7391*e038c9c4Sjoerg // The 'sycl_kernel' attribute applies only to function templates.
7392*e038c9c4Sjoerg const auto *FD = cast<FunctionDecl>(D);
7393*e038c9c4Sjoerg const FunctionTemplateDecl *FT = FD->getDescribedFunctionTemplate();
7394*e038c9c4Sjoerg assert(FT && "Function template is expected");
7395*e038c9c4Sjoerg
7396*e038c9c4Sjoerg // Function template must have at least two template parameters.
7397*e038c9c4Sjoerg const TemplateParameterList *TL = FT->getTemplateParameters();
7398*e038c9c4Sjoerg if (TL->size() < 2) {
7399*e038c9c4Sjoerg S.Diag(FT->getLocation(), diag::warn_sycl_kernel_num_of_template_params);
7400*e038c9c4Sjoerg return;
7401*e038c9c4Sjoerg }
7402*e038c9c4Sjoerg
7403*e038c9c4Sjoerg // Template parameters must be typenames.
7404*e038c9c4Sjoerg for (unsigned I = 0; I < 2; ++I) {
7405*e038c9c4Sjoerg const NamedDecl *TParam = TL->getParam(I);
7406*e038c9c4Sjoerg if (isa<NonTypeTemplateParmDecl>(TParam)) {
7407*e038c9c4Sjoerg S.Diag(FT->getLocation(),
7408*e038c9c4Sjoerg diag::warn_sycl_kernel_invalid_template_param_type);
7409*e038c9c4Sjoerg return;
7410*e038c9c4Sjoerg }
7411*e038c9c4Sjoerg }
7412*e038c9c4Sjoerg
7413*e038c9c4Sjoerg // Function must have at least one argument.
7414*e038c9c4Sjoerg if (getFunctionOrMethodNumParams(D) != 1) {
7415*e038c9c4Sjoerg S.Diag(FT->getLocation(), diag::warn_sycl_kernel_num_of_function_params);
7416*e038c9c4Sjoerg return;
7417*e038c9c4Sjoerg }
7418*e038c9c4Sjoerg
7419*e038c9c4Sjoerg // Function must return void.
7420*e038c9c4Sjoerg QualType RetTy = getFunctionOrMethodResultType(D);
7421*e038c9c4Sjoerg if (!RetTy->isVoidType()) {
7422*e038c9c4Sjoerg S.Diag(FT->getLocation(), diag::warn_sycl_kernel_return_type);
7423*e038c9c4Sjoerg return;
7424*e038c9c4Sjoerg }
7425*e038c9c4Sjoerg
7426*e038c9c4Sjoerg handleSimpleAttribute<SYCLKernelAttr>(S, D, AL);
7427*e038c9c4Sjoerg }
7428*e038c9c4Sjoerg
handleDestroyAttr(Sema & S,Decl * D,const ParsedAttr & A)74297330f729Sjoerg static void handleDestroyAttr(Sema &S, Decl *D, const ParsedAttr &A) {
74307330f729Sjoerg if (!cast<VarDecl>(D)->hasGlobalStorage()) {
74317330f729Sjoerg S.Diag(D->getLocation(), diag::err_destroy_attr_on_non_static_var)
74327330f729Sjoerg << (A.getKind() == ParsedAttr::AT_AlwaysDestroy);
74337330f729Sjoerg return;
74347330f729Sjoerg }
74357330f729Sjoerg
74367330f729Sjoerg if (A.getKind() == ParsedAttr::AT_AlwaysDestroy)
7437*e038c9c4Sjoerg handleSimpleAttribute<AlwaysDestroyAttr>(S, D, A);
74387330f729Sjoerg else
7439*e038c9c4Sjoerg handleSimpleAttribute<NoDestroyAttr>(S, D, A);
74407330f729Sjoerg }
74417330f729Sjoerg
handleUninitializedAttr(Sema & S,Decl * D,const ParsedAttr & AL)74427330f729Sjoerg static void handleUninitializedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
74437330f729Sjoerg assert(cast<VarDecl>(D)->getStorageDuration() == SD_Automatic &&
74447330f729Sjoerg "uninitialized is only valid on automatic duration variables");
74457330f729Sjoerg D->addAttr(::new (S.Context) UninitializedAttr(S.Context, AL));
74467330f729Sjoerg }
74477330f729Sjoerg
tryMakeVariablePseudoStrong(Sema & S,VarDecl * VD,bool DiagnoseFailure)74487330f729Sjoerg static bool tryMakeVariablePseudoStrong(Sema &S, VarDecl *VD,
74497330f729Sjoerg bool DiagnoseFailure) {
74507330f729Sjoerg QualType Ty = VD->getType();
74517330f729Sjoerg if (!Ty->isObjCRetainableType()) {
74527330f729Sjoerg if (DiagnoseFailure) {
74537330f729Sjoerg S.Diag(VD->getBeginLoc(), diag::warn_ignored_objc_externally_retained)
74547330f729Sjoerg << 0;
74557330f729Sjoerg }
74567330f729Sjoerg return false;
74577330f729Sjoerg }
74587330f729Sjoerg
74597330f729Sjoerg Qualifiers::ObjCLifetime LifetimeQual = Ty.getQualifiers().getObjCLifetime();
74607330f729Sjoerg
74617330f729Sjoerg // Sema::inferObjCARCLifetime must run after processing decl attributes
74627330f729Sjoerg // (because __block lowers to an attribute), so if the lifetime hasn't been
74637330f729Sjoerg // explicitly specified, infer it locally now.
74647330f729Sjoerg if (LifetimeQual == Qualifiers::OCL_None)
74657330f729Sjoerg LifetimeQual = Ty->getObjCARCImplicitLifetime();
74667330f729Sjoerg
74677330f729Sjoerg // The attributes only really makes sense for __strong variables; ignore any
74687330f729Sjoerg // attempts to annotate a parameter with any other lifetime qualifier.
74697330f729Sjoerg if (LifetimeQual != Qualifiers::OCL_Strong) {
74707330f729Sjoerg if (DiagnoseFailure) {
74717330f729Sjoerg S.Diag(VD->getBeginLoc(), diag::warn_ignored_objc_externally_retained)
74727330f729Sjoerg << 1;
74737330f729Sjoerg }
74747330f729Sjoerg return false;
74757330f729Sjoerg }
74767330f729Sjoerg
74777330f729Sjoerg // Tampering with the type of a VarDecl here is a bit of a hack, but we need
74787330f729Sjoerg // to ensure that the variable is 'const' so that we can error on
74797330f729Sjoerg // modification, which can otherwise over-release.
74807330f729Sjoerg VD->setType(Ty.withConst());
74817330f729Sjoerg VD->setARCPseudoStrong(true);
74827330f729Sjoerg return true;
74837330f729Sjoerg }
74847330f729Sjoerg
handleObjCExternallyRetainedAttr(Sema & S,Decl * D,const ParsedAttr & AL)74857330f729Sjoerg static void handleObjCExternallyRetainedAttr(Sema &S, Decl *D,
74867330f729Sjoerg const ParsedAttr &AL) {
74877330f729Sjoerg if (auto *VD = dyn_cast<VarDecl>(D)) {
74887330f729Sjoerg assert(!isa<ParmVarDecl>(VD) && "should be diagnosed automatically");
74897330f729Sjoerg if (!VD->hasLocalStorage()) {
74907330f729Sjoerg S.Diag(D->getBeginLoc(), diag::warn_ignored_objc_externally_retained)
74917330f729Sjoerg << 0;
74927330f729Sjoerg return;
74937330f729Sjoerg }
74947330f729Sjoerg
74957330f729Sjoerg if (!tryMakeVariablePseudoStrong(S, VD, /*DiagnoseFailure=*/true))
74967330f729Sjoerg return;
74977330f729Sjoerg
74987330f729Sjoerg handleSimpleAttribute<ObjCExternallyRetainedAttr>(S, D, AL);
74997330f729Sjoerg return;
75007330f729Sjoerg }
75017330f729Sjoerg
75027330f729Sjoerg // If D is a function-like declaration (method, block, or function), then we
75037330f729Sjoerg // make every parameter psuedo-strong.
7504*e038c9c4Sjoerg unsigned NumParams =
7505*e038c9c4Sjoerg hasFunctionProto(D) ? getFunctionOrMethodNumParams(D) : 0;
7506*e038c9c4Sjoerg for (unsigned I = 0; I != NumParams; ++I) {
75077330f729Sjoerg auto *PVD = const_cast<ParmVarDecl *>(getFunctionOrMethodParam(D, I));
75087330f729Sjoerg QualType Ty = PVD->getType();
75097330f729Sjoerg
75107330f729Sjoerg // If a user wrote a parameter with __strong explicitly, then assume they
75117330f729Sjoerg // want "real" strong semantics for that parameter. This works because if
75127330f729Sjoerg // the parameter was written with __strong, then the strong qualifier will
75137330f729Sjoerg // be non-local.
75147330f729Sjoerg if (Ty.getLocalUnqualifiedType().getQualifiers().getObjCLifetime() ==
75157330f729Sjoerg Qualifiers::OCL_Strong)
75167330f729Sjoerg continue;
75177330f729Sjoerg
75187330f729Sjoerg tryMakeVariablePseudoStrong(S, PVD, /*DiagnoseFailure=*/false);
75197330f729Sjoerg }
75207330f729Sjoerg handleSimpleAttribute<ObjCExternallyRetainedAttr>(S, D, AL);
75217330f729Sjoerg }
75227330f729Sjoerg
handleMIGServerRoutineAttr(Sema & S,Decl * D,const ParsedAttr & AL)75237330f729Sjoerg static void handleMIGServerRoutineAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
75247330f729Sjoerg // Check that the return type is a `typedef int kern_return_t` or a typedef
75257330f729Sjoerg // around it, because otherwise MIG convention checks make no sense.
75267330f729Sjoerg // BlockDecl doesn't store a return type, so it's annoying to check,
75277330f729Sjoerg // so let's skip it for now.
75287330f729Sjoerg if (!isa<BlockDecl>(D)) {
75297330f729Sjoerg QualType T = getFunctionOrMethodResultType(D);
75307330f729Sjoerg bool IsKernReturnT = false;
75317330f729Sjoerg while (const auto *TT = T->getAs<TypedefType>()) {
75327330f729Sjoerg IsKernReturnT = (TT->getDecl()->getName() == "kern_return_t");
75337330f729Sjoerg T = TT->desugar();
75347330f729Sjoerg }
75357330f729Sjoerg if (!IsKernReturnT || T.getCanonicalType() != S.getASTContext().IntTy) {
75367330f729Sjoerg S.Diag(D->getBeginLoc(),
75377330f729Sjoerg diag::warn_mig_server_routine_does_not_return_kern_return_t);
75387330f729Sjoerg return;
75397330f729Sjoerg }
75407330f729Sjoerg }
75417330f729Sjoerg
75427330f729Sjoerg handleSimpleAttribute<MIGServerRoutineAttr>(S, D, AL);
75437330f729Sjoerg }
75447330f729Sjoerg
handleMSAllocatorAttr(Sema & S,Decl * D,const ParsedAttr & AL)75457330f729Sjoerg static void handleMSAllocatorAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
75467330f729Sjoerg // Warn if the return type is not a pointer or reference type.
75477330f729Sjoerg if (auto *FD = dyn_cast<FunctionDecl>(D)) {
75487330f729Sjoerg QualType RetTy = FD->getReturnType();
75497330f729Sjoerg if (!RetTy->isPointerType() && !RetTy->isReferenceType()) {
75507330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_declspec_allocator_nonpointer)
75517330f729Sjoerg << AL.getRange() << RetTy;
75527330f729Sjoerg return;
75537330f729Sjoerg }
75547330f729Sjoerg }
75557330f729Sjoerg
75567330f729Sjoerg handleSimpleAttribute<MSAllocatorAttr>(S, D, AL);
75577330f729Sjoerg }
75587330f729Sjoerg
handleAcquireHandleAttr(Sema & S,Decl * D,const ParsedAttr & AL)7559*e038c9c4Sjoerg static void handleAcquireHandleAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
7560*e038c9c4Sjoerg if (AL.isUsedAsTypeAttr())
7561*e038c9c4Sjoerg return;
7562*e038c9c4Sjoerg // Warn if the parameter is definitely not an output parameter.
7563*e038c9c4Sjoerg if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) {
7564*e038c9c4Sjoerg if (PVD->getType()->isIntegerType()) {
7565*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_output_parameter)
7566*e038c9c4Sjoerg << AL.getRange();
7567*e038c9c4Sjoerg return;
7568*e038c9c4Sjoerg }
7569*e038c9c4Sjoerg }
7570*e038c9c4Sjoerg StringRef Argument;
7571*e038c9c4Sjoerg if (!S.checkStringLiteralArgumentAttr(AL, 0, Argument))
7572*e038c9c4Sjoerg return;
7573*e038c9c4Sjoerg D->addAttr(AcquireHandleAttr::Create(S.Context, Argument, AL));
7574*e038c9c4Sjoerg }
7575*e038c9c4Sjoerg
7576*e038c9c4Sjoerg template<typename Attr>
handleHandleAttr(Sema & S,Decl * D,const ParsedAttr & AL)7577*e038c9c4Sjoerg static void handleHandleAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
7578*e038c9c4Sjoerg StringRef Argument;
7579*e038c9c4Sjoerg if (!S.checkStringLiteralArgumentAttr(AL, 0, Argument))
7580*e038c9c4Sjoerg return;
7581*e038c9c4Sjoerg D->addAttr(Attr::Create(S.Context, Argument, AL));
7582*e038c9c4Sjoerg }
7583*e038c9c4Sjoerg
handleCFGuardAttr(Sema & S,Decl * D,const ParsedAttr & AL)7584*e038c9c4Sjoerg static void handleCFGuardAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
7585*e038c9c4Sjoerg // The guard attribute takes a single identifier argument.
7586*e038c9c4Sjoerg
7587*e038c9c4Sjoerg if (!AL.isArgIdent(0)) {
7588*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::err_attribute_argument_type)
7589*e038c9c4Sjoerg << AL << AANT_ArgumentIdentifier;
7590*e038c9c4Sjoerg return;
7591*e038c9c4Sjoerg }
7592*e038c9c4Sjoerg
7593*e038c9c4Sjoerg CFGuardAttr::GuardArg Arg;
7594*e038c9c4Sjoerg IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
7595*e038c9c4Sjoerg if (!CFGuardAttr::ConvertStrToGuardArg(II->getName(), Arg)) {
7596*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_type_not_supported) << AL << II;
7597*e038c9c4Sjoerg return;
7598*e038c9c4Sjoerg }
7599*e038c9c4Sjoerg
7600*e038c9c4Sjoerg D->addAttr(::new (S.Context) CFGuardAttr(S.Context, AL, Arg));
7601*e038c9c4Sjoerg }
7602*e038c9c4Sjoerg
7603*e038c9c4Sjoerg
7604*e038c9c4Sjoerg template <typename AttrTy>
findEnforceTCBAttrByName(Decl * D,StringRef Name)7605*e038c9c4Sjoerg static const AttrTy *findEnforceTCBAttrByName(Decl *D, StringRef Name) {
7606*e038c9c4Sjoerg auto Attrs = D->specific_attrs<AttrTy>();
7607*e038c9c4Sjoerg auto I = llvm::find_if(Attrs,
7608*e038c9c4Sjoerg [Name](const AttrTy *A) {
7609*e038c9c4Sjoerg return A->getTCBName() == Name;
7610*e038c9c4Sjoerg });
7611*e038c9c4Sjoerg return I == Attrs.end() ? nullptr : *I;
7612*e038c9c4Sjoerg }
7613*e038c9c4Sjoerg
7614*e038c9c4Sjoerg template <typename AttrTy, typename ConflictingAttrTy>
handleEnforceTCBAttr(Sema & S,Decl * D,const ParsedAttr & AL)7615*e038c9c4Sjoerg static void handleEnforceTCBAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
7616*e038c9c4Sjoerg StringRef Argument;
7617*e038c9c4Sjoerg if (!S.checkStringLiteralArgumentAttr(AL, 0, Argument))
7618*e038c9c4Sjoerg return;
7619*e038c9c4Sjoerg
7620*e038c9c4Sjoerg // A function cannot be have both regular and leaf membership in the same TCB.
7621*e038c9c4Sjoerg if (const ConflictingAttrTy *ConflictingAttr =
7622*e038c9c4Sjoerg findEnforceTCBAttrByName<ConflictingAttrTy>(D, Argument)) {
7623*e038c9c4Sjoerg // We could attach a note to the other attribute but in this case
7624*e038c9c4Sjoerg // there's no need given how the two are very close to each other.
7625*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::err_tcb_conflicting_attributes)
7626*e038c9c4Sjoerg << AL.getAttrName()->getName() << ConflictingAttr->getAttrName()->getName()
7627*e038c9c4Sjoerg << Argument;
7628*e038c9c4Sjoerg
7629*e038c9c4Sjoerg // Error recovery: drop the non-leaf attribute so that to suppress
7630*e038c9c4Sjoerg // all future warnings caused by erroneous attributes. The leaf attribute
7631*e038c9c4Sjoerg // needs to be kept because it can only suppresses warnings, not cause them.
7632*e038c9c4Sjoerg D->dropAttr<EnforceTCBAttr>();
7633*e038c9c4Sjoerg return;
7634*e038c9c4Sjoerg }
7635*e038c9c4Sjoerg
7636*e038c9c4Sjoerg D->addAttr(AttrTy::Create(S.Context, Argument, AL));
7637*e038c9c4Sjoerg }
7638*e038c9c4Sjoerg
7639*e038c9c4Sjoerg template <typename AttrTy, typename ConflictingAttrTy>
mergeEnforceTCBAttrImpl(Sema & S,Decl * D,const AttrTy & AL)7640*e038c9c4Sjoerg static AttrTy *mergeEnforceTCBAttrImpl(Sema &S, Decl *D, const AttrTy &AL) {
7641*e038c9c4Sjoerg // Check if the new redeclaration has different leaf-ness in the same TCB.
7642*e038c9c4Sjoerg StringRef TCBName = AL.getTCBName();
7643*e038c9c4Sjoerg if (const ConflictingAttrTy *ConflictingAttr =
7644*e038c9c4Sjoerg findEnforceTCBAttrByName<ConflictingAttrTy>(D, TCBName)) {
7645*e038c9c4Sjoerg S.Diag(ConflictingAttr->getLoc(), diag::err_tcb_conflicting_attributes)
7646*e038c9c4Sjoerg << ConflictingAttr->getAttrName()->getName()
7647*e038c9c4Sjoerg << AL.getAttrName()->getName() << TCBName;
7648*e038c9c4Sjoerg
7649*e038c9c4Sjoerg // Add a note so that the user could easily find the conflicting attribute.
7650*e038c9c4Sjoerg S.Diag(AL.getLoc(), diag::note_conflicting_attribute);
7651*e038c9c4Sjoerg
7652*e038c9c4Sjoerg // More error recovery.
7653*e038c9c4Sjoerg D->dropAttr<EnforceTCBAttr>();
7654*e038c9c4Sjoerg return nullptr;
7655*e038c9c4Sjoerg }
7656*e038c9c4Sjoerg
7657*e038c9c4Sjoerg ASTContext &Context = S.getASTContext();
7658*e038c9c4Sjoerg return ::new(Context) AttrTy(Context, AL, AL.getTCBName());
7659*e038c9c4Sjoerg }
7660*e038c9c4Sjoerg
mergeEnforceTCBAttr(Decl * D,const EnforceTCBAttr & AL)7661*e038c9c4Sjoerg EnforceTCBAttr *Sema::mergeEnforceTCBAttr(Decl *D, const EnforceTCBAttr &AL) {
7662*e038c9c4Sjoerg return mergeEnforceTCBAttrImpl<EnforceTCBAttr, EnforceTCBLeafAttr>(
7663*e038c9c4Sjoerg *this, D, AL);
7664*e038c9c4Sjoerg }
7665*e038c9c4Sjoerg
mergeEnforceTCBLeafAttr(Decl * D,const EnforceTCBLeafAttr & AL)7666*e038c9c4Sjoerg EnforceTCBLeafAttr *Sema::mergeEnforceTCBLeafAttr(
7667*e038c9c4Sjoerg Decl *D, const EnforceTCBLeafAttr &AL) {
7668*e038c9c4Sjoerg return mergeEnforceTCBAttrImpl<EnforceTCBLeafAttr, EnforceTCBAttr>(
7669*e038c9c4Sjoerg *this, D, AL);
7670*e038c9c4Sjoerg }
7671*e038c9c4Sjoerg
76727330f729Sjoerg //===----------------------------------------------------------------------===//
76737330f729Sjoerg // Top Level Sema Entry Points
76747330f729Sjoerg //===----------------------------------------------------------------------===//
76757330f729Sjoerg
76767330f729Sjoerg /// ProcessDeclAttribute - Apply the specific attribute to the specified decl if
76777330f729Sjoerg /// the attribute applies to decls. If the attribute is a type attribute, just
76787330f729Sjoerg /// silently ignore it if a GNU attribute.
ProcessDeclAttribute(Sema & S,Scope * scope,Decl * D,const ParsedAttr & AL,bool IncludeCXX11Attributes)76797330f729Sjoerg static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
76807330f729Sjoerg const ParsedAttr &AL,
76817330f729Sjoerg bool IncludeCXX11Attributes) {
76827330f729Sjoerg if (AL.isInvalid() || AL.getKind() == ParsedAttr::IgnoredAttribute)
76837330f729Sjoerg return;
76847330f729Sjoerg
76857330f729Sjoerg // Ignore C++11 attributes on declarator chunks: they appertain to the type
76867330f729Sjoerg // instead.
76877330f729Sjoerg if (AL.isCXX11Attribute() && !IncludeCXX11Attributes)
76887330f729Sjoerg return;
76897330f729Sjoerg
76907330f729Sjoerg // Unknown attributes are automatically warned on. Target-specific attributes
76917330f729Sjoerg // which do not apply to the current target architecture are treated as
76927330f729Sjoerg // though they were unknown attributes.
76937330f729Sjoerg if (AL.getKind() == ParsedAttr::UnknownAttribute ||
76947330f729Sjoerg !AL.existsInTarget(S.Context.getTargetInfo())) {
76957330f729Sjoerg S.Diag(AL.getLoc(),
76967330f729Sjoerg AL.isDeclspecAttribute()
76977330f729Sjoerg ? (unsigned)diag::warn_unhandled_ms_attribute_ignored
76987330f729Sjoerg : (unsigned)diag::warn_unknown_attribute_ignored)
7699*e038c9c4Sjoerg << AL << AL.getRange();
77007330f729Sjoerg return;
77017330f729Sjoerg }
77027330f729Sjoerg
7703*e038c9c4Sjoerg if (S.checkCommonAttributeFeatures(D, AL))
77047330f729Sjoerg return;
77057330f729Sjoerg
77067330f729Sjoerg switch (AL.getKind()) {
77077330f729Sjoerg default:
7708*e038c9c4Sjoerg if (AL.getInfo().handleDeclAttribute(S, D, AL) != ParsedAttrInfo::NotHandled)
7709*e038c9c4Sjoerg break;
77107330f729Sjoerg if (!AL.isStmtAttr()) {
77117330f729Sjoerg // Type attributes are handled elsewhere; silently move on.
77127330f729Sjoerg assert(AL.isTypeAttr() && "Non-type attribute not handled");
77137330f729Sjoerg break;
77147330f729Sjoerg }
7715*e038c9c4Sjoerg // N.B., ClangAttrEmitter.cpp emits a diagnostic helper that ensures a
7716*e038c9c4Sjoerg // statement attribute is not written on a declaration, but this code is
7717*e038c9c4Sjoerg // needed for attributes in Attr.td that do not list any subjects.
77187330f729Sjoerg S.Diag(AL.getLoc(), diag::err_stmt_attribute_invalid_on_decl)
77197330f729Sjoerg << AL << D->getLocation();
77207330f729Sjoerg break;
77217330f729Sjoerg case ParsedAttr::AT_Interrupt:
77227330f729Sjoerg handleInterruptAttr(S, D, AL);
77237330f729Sjoerg break;
77247330f729Sjoerg case ParsedAttr::AT_X86ForceAlignArgPointer:
77257330f729Sjoerg handleX86ForceAlignArgPointerAttr(S, D, AL);
77267330f729Sjoerg break;
77277330f729Sjoerg case ParsedAttr::AT_DLLExport:
77287330f729Sjoerg case ParsedAttr::AT_DLLImport:
77297330f729Sjoerg handleDLLAttr(S, D, AL);
77307330f729Sjoerg break;
77317330f729Sjoerg case ParsedAttr::AT_AMDGPUFlatWorkGroupSize:
77327330f729Sjoerg handleAMDGPUFlatWorkGroupSizeAttr(S, D, AL);
77337330f729Sjoerg break;
77347330f729Sjoerg case ParsedAttr::AT_AMDGPUWavesPerEU:
77357330f729Sjoerg handleAMDGPUWavesPerEUAttr(S, D, AL);
77367330f729Sjoerg break;
77377330f729Sjoerg case ParsedAttr::AT_AMDGPUNumSGPR:
77387330f729Sjoerg handleAMDGPUNumSGPRAttr(S, D, AL);
77397330f729Sjoerg break;
77407330f729Sjoerg case ParsedAttr::AT_AMDGPUNumVGPR:
77417330f729Sjoerg handleAMDGPUNumVGPRAttr(S, D, AL);
77427330f729Sjoerg break;
77437330f729Sjoerg case ParsedAttr::AT_AVRSignal:
77447330f729Sjoerg handleAVRSignalAttr(S, D, AL);
77457330f729Sjoerg break;
7746*e038c9c4Sjoerg case ParsedAttr::AT_BPFPreserveAccessIndex:
7747*e038c9c4Sjoerg handleBPFPreserveAccessIndexAttr(S, D, AL);
7748*e038c9c4Sjoerg break;
7749*e038c9c4Sjoerg case ParsedAttr::AT_WebAssemblyExportName:
7750*e038c9c4Sjoerg handleWebAssemblyExportNameAttr(S, D, AL);
7751*e038c9c4Sjoerg break;
77527330f729Sjoerg case ParsedAttr::AT_WebAssemblyImportModule:
77537330f729Sjoerg handleWebAssemblyImportModuleAttr(S, D, AL);
77547330f729Sjoerg break;
77557330f729Sjoerg case ParsedAttr::AT_WebAssemblyImportName:
77567330f729Sjoerg handleWebAssemblyImportNameAttr(S, D, AL);
77577330f729Sjoerg break;
77587330f729Sjoerg case ParsedAttr::AT_IBOutlet:
77597330f729Sjoerg handleIBOutlet(S, D, AL);
77607330f729Sjoerg break;
77617330f729Sjoerg case ParsedAttr::AT_IBOutletCollection:
77627330f729Sjoerg handleIBOutletCollection(S, D, AL);
77637330f729Sjoerg break;
77647330f729Sjoerg case ParsedAttr::AT_IFunc:
77657330f729Sjoerg handleIFuncAttr(S, D, AL);
77667330f729Sjoerg break;
77677330f729Sjoerg case ParsedAttr::AT_Alias:
77687330f729Sjoerg handleAliasAttr(S, D, AL);
77697330f729Sjoerg break;
77707330f729Sjoerg case ParsedAttr::AT_Aligned:
77717330f729Sjoerg handleAlignedAttr(S, D, AL);
77727330f729Sjoerg break;
77737330f729Sjoerg case ParsedAttr::AT_AlignValue:
77747330f729Sjoerg handleAlignValueAttr(S, D, AL);
77757330f729Sjoerg break;
77767330f729Sjoerg case ParsedAttr::AT_AllocSize:
77777330f729Sjoerg handleAllocSizeAttr(S, D, AL);
77787330f729Sjoerg break;
77797330f729Sjoerg case ParsedAttr::AT_AlwaysInline:
77807330f729Sjoerg handleAlwaysInlineAttr(S, D, AL);
77817330f729Sjoerg break;
77827330f729Sjoerg case ParsedAttr::AT_AnalyzerNoReturn:
77837330f729Sjoerg handleAnalyzerNoReturnAttr(S, D, AL);
77847330f729Sjoerg break;
77857330f729Sjoerg case ParsedAttr::AT_TLSModel:
77867330f729Sjoerg handleTLSModelAttr(S, D, AL);
77877330f729Sjoerg break;
77887330f729Sjoerg case ParsedAttr::AT_Annotate:
77897330f729Sjoerg handleAnnotateAttr(S, D, AL);
77907330f729Sjoerg break;
77917330f729Sjoerg case ParsedAttr::AT_Availability:
77927330f729Sjoerg handleAvailabilityAttr(S, D, AL);
77937330f729Sjoerg break;
77947330f729Sjoerg case ParsedAttr::AT_CarriesDependency:
77957330f729Sjoerg handleDependencyAttr(S, scope, D, AL);
77967330f729Sjoerg break;
77977330f729Sjoerg case ParsedAttr::AT_CPUDispatch:
77987330f729Sjoerg case ParsedAttr::AT_CPUSpecific:
77997330f729Sjoerg handleCPUSpecificAttr(S, D, AL);
78007330f729Sjoerg break;
78017330f729Sjoerg case ParsedAttr::AT_Common:
78027330f729Sjoerg handleCommonAttr(S, D, AL);
78037330f729Sjoerg break;
78047330f729Sjoerg case ParsedAttr::AT_CUDAConstant:
78057330f729Sjoerg handleConstantAttr(S, D, AL);
78067330f729Sjoerg break;
78077330f729Sjoerg case ParsedAttr::AT_PassObjectSize:
78087330f729Sjoerg handlePassObjectSizeAttr(S, D, AL);
78097330f729Sjoerg break;
78107330f729Sjoerg case ParsedAttr::AT_Constructor:
78117330f729Sjoerg handleConstructorAttr(S, D, AL);
78127330f729Sjoerg break;
78137330f729Sjoerg case ParsedAttr::AT_Deprecated:
78147330f729Sjoerg handleDeprecatedAttr(S, D, AL);
78157330f729Sjoerg break;
78167330f729Sjoerg case ParsedAttr::AT_Destructor:
78177330f729Sjoerg handleDestructorAttr(S, D, AL);
78187330f729Sjoerg break;
78197330f729Sjoerg case ParsedAttr::AT_EnableIf:
78207330f729Sjoerg handleEnableIfAttr(S, D, AL);
78217330f729Sjoerg break;
78227330f729Sjoerg case ParsedAttr::AT_DiagnoseIf:
78237330f729Sjoerg handleDiagnoseIfAttr(S, D, AL);
78247330f729Sjoerg break;
7825*e038c9c4Sjoerg case ParsedAttr::AT_NoBuiltin:
7826*e038c9c4Sjoerg handleNoBuiltinAttr(S, D, AL);
7827*e038c9c4Sjoerg break;
78287330f729Sjoerg case ParsedAttr::AT_ExtVectorType:
78297330f729Sjoerg handleExtVectorTypeAttr(S, D, AL);
78307330f729Sjoerg break;
78317330f729Sjoerg case ParsedAttr::AT_ExternalSourceSymbol:
78327330f729Sjoerg handleExternalSourceSymbolAttr(S, D, AL);
78337330f729Sjoerg break;
78347330f729Sjoerg case ParsedAttr::AT_MinSize:
78357330f729Sjoerg handleMinSizeAttr(S, D, AL);
78367330f729Sjoerg break;
78377330f729Sjoerg case ParsedAttr::AT_OptimizeNone:
78387330f729Sjoerg handleOptimizeNoneAttr(S, D, AL);
78397330f729Sjoerg break;
78407330f729Sjoerg case ParsedAttr::AT_EnumExtensibility:
78417330f729Sjoerg handleEnumExtensibilityAttr(S, D, AL);
78427330f729Sjoerg break;
7843*e038c9c4Sjoerg case ParsedAttr::AT_SYCLKernel:
7844*e038c9c4Sjoerg handleSYCLKernelAttr(S, D, AL);
78457330f729Sjoerg break;
78467330f729Sjoerg case ParsedAttr::AT_Format:
78477330f729Sjoerg handleFormatAttr(S, D, AL);
78487330f729Sjoerg break;
78497330f729Sjoerg case ParsedAttr::AT_FormatArg:
78507330f729Sjoerg handleFormatArgAttr(S, D, AL);
78517330f729Sjoerg break;
78527330f729Sjoerg case ParsedAttr::AT_Callback:
78537330f729Sjoerg handleCallbackAttr(S, D, AL);
78547330f729Sjoerg break;
7855*e038c9c4Sjoerg case ParsedAttr::AT_CalledOnce:
7856*e038c9c4Sjoerg handleCalledOnceAttr(S, D, AL);
7857*e038c9c4Sjoerg break;
78587330f729Sjoerg case ParsedAttr::AT_CUDAGlobal:
78597330f729Sjoerg handleGlobalAttr(S, D, AL);
78607330f729Sjoerg break;
78617330f729Sjoerg case ParsedAttr::AT_CUDADevice:
7862*e038c9c4Sjoerg handleDeviceAttr(S, D, AL);
78637330f729Sjoerg break;
7864*e038c9c4Sjoerg case ParsedAttr::AT_HIPManaged:
7865*e038c9c4Sjoerg handleManagedAttr(S, D, AL);
78667330f729Sjoerg break;
78677330f729Sjoerg case ParsedAttr::AT_GNUInline:
78687330f729Sjoerg handleGNUInlineAttr(S, D, AL);
78697330f729Sjoerg break;
78707330f729Sjoerg case ParsedAttr::AT_CUDALaunchBounds:
78717330f729Sjoerg handleLaunchBoundsAttr(S, D, AL);
78727330f729Sjoerg break;
78737330f729Sjoerg case ParsedAttr::AT_Restrict:
78747330f729Sjoerg handleRestrictAttr(S, D, AL);
78757330f729Sjoerg break;
78767330f729Sjoerg case ParsedAttr::AT_Mode:
78777330f729Sjoerg handleModeAttr(S, D, AL);
78787330f729Sjoerg break;
78797330f729Sjoerg case ParsedAttr::AT_NonNull:
78807330f729Sjoerg if (auto *PVD = dyn_cast<ParmVarDecl>(D))
78817330f729Sjoerg handleNonNullAttrParameter(S, PVD, AL);
78827330f729Sjoerg else
78837330f729Sjoerg handleNonNullAttr(S, D, AL);
78847330f729Sjoerg break;
78857330f729Sjoerg case ParsedAttr::AT_ReturnsNonNull:
78867330f729Sjoerg handleReturnsNonNullAttr(S, D, AL);
78877330f729Sjoerg break;
78887330f729Sjoerg case ParsedAttr::AT_NoEscape:
78897330f729Sjoerg handleNoEscapeAttr(S, D, AL);
78907330f729Sjoerg break;
78917330f729Sjoerg case ParsedAttr::AT_AssumeAligned:
78927330f729Sjoerg handleAssumeAlignedAttr(S, D, AL);
78937330f729Sjoerg break;
78947330f729Sjoerg case ParsedAttr::AT_AllocAlign:
78957330f729Sjoerg handleAllocAlignAttr(S, D, AL);
78967330f729Sjoerg break;
78977330f729Sjoerg case ParsedAttr::AT_Ownership:
78987330f729Sjoerg handleOwnershipAttr(S, D, AL);
78997330f729Sjoerg break;
79007330f729Sjoerg case ParsedAttr::AT_Naked:
79017330f729Sjoerg handleNakedAttr(S, D, AL);
79027330f729Sjoerg break;
79037330f729Sjoerg case ParsedAttr::AT_NoReturn:
79047330f729Sjoerg handleNoReturnAttr(S, D, AL);
79057330f729Sjoerg break;
79067330f729Sjoerg case ParsedAttr::AT_AnyX86NoCfCheck:
79077330f729Sjoerg handleNoCfCheckAttr(S, D, AL);
79087330f729Sjoerg break;
79097330f729Sjoerg case ParsedAttr::AT_NoThrow:
79107330f729Sjoerg if (!AL.isUsedAsTypeAttr())
79117330f729Sjoerg handleSimpleAttribute<NoThrowAttr>(S, D, AL);
79127330f729Sjoerg break;
79137330f729Sjoerg case ParsedAttr::AT_CUDAShared:
79147330f729Sjoerg handleSharedAttr(S, D, AL);
79157330f729Sjoerg break;
79167330f729Sjoerg case ParsedAttr::AT_VecReturn:
79177330f729Sjoerg handleVecReturnAttr(S, D, AL);
79187330f729Sjoerg break;
79197330f729Sjoerg case ParsedAttr::AT_ObjCOwnership:
79207330f729Sjoerg handleObjCOwnershipAttr(S, D, AL);
79217330f729Sjoerg break;
79227330f729Sjoerg case ParsedAttr::AT_ObjCPreciseLifetime:
79237330f729Sjoerg handleObjCPreciseLifetimeAttr(S, D, AL);
79247330f729Sjoerg break;
79257330f729Sjoerg case ParsedAttr::AT_ObjCReturnsInnerPointer:
79267330f729Sjoerg handleObjCReturnsInnerPointerAttr(S, D, AL);
79277330f729Sjoerg break;
79287330f729Sjoerg case ParsedAttr::AT_ObjCRequiresSuper:
79297330f729Sjoerg handleObjCRequiresSuperAttr(S, D, AL);
79307330f729Sjoerg break;
79317330f729Sjoerg case ParsedAttr::AT_ObjCBridge:
79327330f729Sjoerg handleObjCBridgeAttr(S, D, AL);
79337330f729Sjoerg break;
79347330f729Sjoerg case ParsedAttr::AT_ObjCBridgeMutable:
79357330f729Sjoerg handleObjCBridgeMutableAttr(S, D, AL);
79367330f729Sjoerg break;
79377330f729Sjoerg case ParsedAttr::AT_ObjCBridgeRelated:
79387330f729Sjoerg handleObjCBridgeRelatedAttr(S, D, AL);
79397330f729Sjoerg break;
79407330f729Sjoerg case ParsedAttr::AT_ObjCDesignatedInitializer:
79417330f729Sjoerg handleObjCDesignatedInitializer(S, D, AL);
79427330f729Sjoerg break;
79437330f729Sjoerg case ParsedAttr::AT_ObjCRuntimeName:
79447330f729Sjoerg handleObjCRuntimeName(S, D, AL);
79457330f729Sjoerg break;
79467330f729Sjoerg case ParsedAttr::AT_ObjCBoxable:
79477330f729Sjoerg handleObjCBoxable(S, D, AL);
79487330f729Sjoerg break;
7949*e038c9c4Sjoerg case ParsedAttr::AT_NSErrorDomain:
7950*e038c9c4Sjoerg handleNSErrorDomain(S, D, AL);
79517330f729Sjoerg break;
79527330f729Sjoerg case ParsedAttr::AT_CFConsumed:
79537330f729Sjoerg case ParsedAttr::AT_NSConsumed:
79547330f729Sjoerg case ParsedAttr::AT_OSConsumed:
79557330f729Sjoerg S.AddXConsumedAttr(D, AL, parsedAttrToRetainOwnershipKind(AL),
79567330f729Sjoerg /*IsTemplateInstantiation=*/false);
79577330f729Sjoerg break;
79587330f729Sjoerg case ParsedAttr::AT_OSReturnsRetainedOnZero:
79597330f729Sjoerg handleSimpleAttributeOrDiagnose<OSReturnsRetainedOnZeroAttr>(
79607330f729Sjoerg S, D, AL, isValidOSObjectOutParameter(D),
79617330f729Sjoerg diag::warn_ns_attribute_wrong_parameter_type,
79627330f729Sjoerg /*Extra Args=*/AL, /*pointer-to-OSObject-pointer*/ 3, AL.getRange());
79637330f729Sjoerg break;
79647330f729Sjoerg case ParsedAttr::AT_OSReturnsRetainedOnNonZero:
79657330f729Sjoerg handleSimpleAttributeOrDiagnose<OSReturnsRetainedOnNonZeroAttr>(
79667330f729Sjoerg S, D, AL, isValidOSObjectOutParameter(D),
79677330f729Sjoerg diag::warn_ns_attribute_wrong_parameter_type,
79687330f729Sjoerg /*Extra Args=*/AL, /*pointer-to-OSObject-poointer*/ 3, AL.getRange());
79697330f729Sjoerg break;
79707330f729Sjoerg case ParsedAttr::AT_NSReturnsAutoreleased:
79717330f729Sjoerg case ParsedAttr::AT_NSReturnsNotRetained:
79727330f729Sjoerg case ParsedAttr::AT_NSReturnsRetained:
79737330f729Sjoerg case ParsedAttr::AT_CFReturnsNotRetained:
79747330f729Sjoerg case ParsedAttr::AT_CFReturnsRetained:
79757330f729Sjoerg case ParsedAttr::AT_OSReturnsNotRetained:
79767330f729Sjoerg case ParsedAttr::AT_OSReturnsRetained:
79777330f729Sjoerg handleXReturnsXRetainedAttr(S, D, AL);
79787330f729Sjoerg break;
79797330f729Sjoerg case ParsedAttr::AT_WorkGroupSizeHint:
79807330f729Sjoerg handleWorkGroupSize<WorkGroupSizeHintAttr>(S, D, AL);
79817330f729Sjoerg break;
79827330f729Sjoerg case ParsedAttr::AT_ReqdWorkGroupSize:
79837330f729Sjoerg handleWorkGroupSize<ReqdWorkGroupSizeAttr>(S, D, AL);
79847330f729Sjoerg break;
79857330f729Sjoerg case ParsedAttr::AT_OpenCLIntelReqdSubGroupSize:
79867330f729Sjoerg handleSubGroupSize(S, D, AL);
79877330f729Sjoerg break;
79887330f729Sjoerg case ParsedAttr::AT_VecTypeHint:
79897330f729Sjoerg handleVecTypeHint(S, D, AL);
79907330f729Sjoerg break;
79917330f729Sjoerg case ParsedAttr::AT_InitPriority:
79927330f729Sjoerg handleInitPriorityAttr(S, D, AL);
79937330f729Sjoerg break;
79947330f729Sjoerg case ParsedAttr::AT_Packed:
79957330f729Sjoerg handlePackedAttr(S, D, AL);
79967330f729Sjoerg break;
7997*e038c9c4Sjoerg case ParsedAttr::AT_PreferredName:
7998*e038c9c4Sjoerg handlePreferredName(S, D, AL);
7999*e038c9c4Sjoerg break;
80007330f729Sjoerg case ParsedAttr::AT_Section:
80017330f729Sjoerg handleSectionAttr(S, D, AL);
80027330f729Sjoerg break;
80037330f729Sjoerg case ParsedAttr::AT_CodeSeg:
80047330f729Sjoerg handleCodeSegAttr(S, D, AL);
80057330f729Sjoerg break;
80067330f729Sjoerg case ParsedAttr::AT_Target:
80077330f729Sjoerg handleTargetAttr(S, D, AL);
80087330f729Sjoerg break;
80097330f729Sjoerg case ParsedAttr::AT_MinVectorWidth:
80107330f729Sjoerg handleMinVectorWidthAttr(S, D, AL);
80117330f729Sjoerg break;
80127330f729Sjoerg case ParsedAttr::AT_Unavailable:
80137330f729Sjoerg handleAttrWithMessage<UnavailableAttr>(S, D, AL);
80147330f729Sjoerg break;
8015*e038c9c4Sjoerg case ParsedAttr::AT_Assumption:
8016*e038c9c4Sjoerg handleAssumumptionAttr(S, D, AL);
80177330f729Sjoerg break;
8018*e038c9c4Sjoerg case ParsedAttr::AT_ObjCDirect:
8019*e038c9c4Sjoerg handleObjCDirectAttr(S, D, AL);
80207330f729Sjoerg break;
8021*e038c9c4Sjoerg case ParsedAttr::AT_ObjCDirectMembers:
8022*e038c9c4Sjoerg handleObjCDirectMembersAttr(S, D, AL);
8023*e038c9c4Sjoerg handleSimpleAttribute<ObjCDirectMembersAttr>(S, D, AL);
80247330f729Sjoerg break;
80257330f729Sjoerg case ParsedAttr::AT_ObjCExplicitProtocolImpl:
80267330f729Sjoerg handleObjCSuppresProtocolAttr(S, D, AL);
80277330f729Sjoerg break;
80287330f729Sjoerg case ParsedAttr::AT_Unused:
80297330f729Sjoerg handleUnusedAttr(S, D, AL);
80307330f729Sjoerg break;
80317330f729Sjoerg case ParsedAttr::AT_Visibility:
80327330f729Sjoerg handleVisibilityAttr(S, D, AL, false);
80337330f729Sjoerg break;
80347330f729Sjoerg case ParsedAttr::AT_TypeVisibility:
80357330f729Sjoerg handleVisibilityAttr(S, D, AL, true);
80367330f729Sjoerg break;
80377330f729Sjoerg case ParsedAttr::AT_WarnUnusedResult:
80387330f729Sjoerg handleWarnUnusedResult(S, D, AL);
80397330f729Sjoerg break;
80407330f729Sjoerg case ParsedAttr::AT_WeakRef:
80417330f729Sjoerg handleWeakRefAttr(S, D, AL);
80427330f729Sjoerg break;
80437330f729Sjoerg case ParsedAttr::AT_WeakImport:
80447330f729Sjoerg handleWeakImportAttr(S, D, AL);
80457330f729Sjoerg break;
80467330f729Sjoerg case ParsedAttr::AT_TransparentUnion:
80477330f729Sjoerg handleTransparentUnionAttr(S, D, AL);
80487330f729Sjoerg break;
80497330f729Sjoerg case ParsedAttr::AT_ObjCMethodFamily:
80507330f729Sjoerg handleObjCMethodFamilyAttr(S, D, AL);
80517330f729Sjoerg break;
80527330f729Sjoerg case ParsedAttr::AT_ObjCNSObject:
80537330f729Sjoerg handleObjCNSObject(S, D, AL);
80547330f729Sjoerg break;
80557330f729Sjoerg case ParsedAttr::AT_ObjCIndependentClass:
80567330f729Sjoerg handleObjCIndependentClass(S, D, AL);
80577330f729Sjoerg break;
80587330f729Sjoerg case ParsedAttr::AT_Blocks:
80597330f729Sjoerg handleBlocksAttr(S, D, AL);
80607330f729Sjoerg break;
80617330f729Sjoerg case ParsedAttr::AT_Sentinel:
80627330f729Sjoerg handleSentinelAttr(S, D, AL);
80637330f729Sjoerg break;
80647330f729Sjoerg case ParsedAttr::AT_Cleanup:
80657330f729Sjoerg handleCleanupAttr(S, D, AL);
80667330f729Sjoerg break;
80677330f729Sjoerg case ParsedAttr::AT_NoDebug:
80687330f729Sjoerg handleNoDebugAttr(S, D, AL);
80697330f729Sjoerg break;
8070*e038c9c4Sjoerg case ParsedAttr::AT_CmseNSEntry:
8071*e038c9c4Sjoerg handleCmseNSEntryAttr(S, D, AL);
80727330f729Sjoerg break;
80737330f729Sjoerg case ParsedAttr::AT_StdCall:
80747330f729Sjoerg case ParsedAttr::AT_CDecl:
80757330f729Sjoerg case ParsedAttr::AT_FastCall:
80767330f729Sjoerg case ParsedAttr::AT_ThisCall:
80777330f729Sjoerg case ParsedAttr::AT_Pascal:
80787330f729Sjoerg case ParsedAttr::AT_RegCall:
80797330f729Sjoerg case ParsedAttr::AT_SwiftCall:
80807330f729Sjoerg case ParsedAttr::AT_VectorCall:
80817330f729Sjoerg case ParsedAttr::AT_MSABI:
80827330f729Sjoerg case ParsedAttr::AT_SysVABI:
80837330f729Sjoerg case ParsedAttr::AT_Pcs:
80847330f729Sjoerg case ParsedAttr::AT_IntelOclBicc:
80857330f729Sjoerg case ParsedAttr::AT_PreserveMost:
80867330f729Sjoerg case ParsedAttr::AT_PreserveAll:
80877330f729Sjoerg case ParsedAttr::AT_AArch64VectorPcs:
80887330f729Sjoerg handleCallConvAttr(S, D, AL);
80897330f729Sjoerg break;
80907330f729Sjoerg case ParsedAttr::AT_Suppress:
80917330f729Sjoerg handleSuppressAttr(S, D, AL);
80927330f729Sjoerg break;
80937330f729Sjoerg case ParsedAttr::AT_Owner:
80947330f729Sjoerg case ParsedAttr::AT_Pointer:
80957330f729Sjoerg handleLifetimeCategoryAttr(S, D, AL);
80967330f729Sjoerg break;
80977330f729Sjoerg case ParsedAttr::AT_OpenCLAccess:
80987330f729Sjoerg handleOpenCLAccessAttr(S, D, AL);
80997330f729Sjoerg break;
81007330f729Sjoerg case ParsedAttr::AT_OpenCLNoSVM:
81017330f729Sjoerg handleOpenCLNoSVMAttr(S, D, AL);
81027330f729Sjoerg break;
81037330f729Sjoerg case ParsedAttr::AT_SwiftContext:
81047330f729Sjoerg S.AddParameterABIAttr(D, AL, ParameterABI::SwiftContext);
81057330f729Sjoerg break;
81067330f729Sjoerg case ParsedAttr::AT_SwiftErrorResult:
81077330f729Sjoerg S.AddParameterABIAttr(D, AL, ParameterABI::SwiftErrorResult);
81087330f729Sjoerg break;
81097330f729Sjoerg case ParsedAttr::AT_SwiftIndirectResult:
81107330f729Sjoerg S.AddParameterABIAttr(D, AL, ParameterABI::SwiftIndirectResult);
81117330f729Sjoerg break;
81127330f729Sjoerg case ParsedAttr::AT_InternalLinkage:
81137330f729Sjoerg handleInternalLinkageAttr(S, D, AL);
81147330f729Sjoerg break;
81157330f729Sjoerg
81167330f729Sjoerg // Microsoft attributes:
81177330f729Sjoerg case ParsedAttr::AT_LayoutVersion:
81187330f729Sjoerg handleLayoutVersion(S, D, AL);
81197330f729Sjoerg break;
81207330f729Sjoerg case ParsedAttr::AT_Uuid:
81217330f729Sjoerg handleUuidAttr(S, D, AL);
81227330f729Sjoerg break;
81237330f729Sjoerg case ParsedAttr::AT_MSInheritance:
81247330f729Sjoerg handleMSInheritanceAttr(S, D, AL);
81257330f729Sjoerg break;
81267330f729Sjoerg case ParsedAttr::AT_Thread:
81277330f729Sjoerg handleDeclspecThreadAttr(S, D, AL);
81287330f729Sjoerg break;
81297330f729Sjoerg
81307330f729Sjoerg case ParsedAttr::AT_AbiTag:
81317330f729Sjoerg handleAbiTagAttr(S, D, AL);
81327330f729Sjoerg break;
8133*e038c9c4Sjoerg case ParsedAttr::AT_CFGuard:
8134*e038c9c4Sjoerg handleCFGuardAttr(S, D, AL);
8135*e038c9c4Sjoerg break;
81367330f729Sjoerg
81377330f729Sjoerg // Thread safety attributes:
81387330f729Sjoerg case ParsedAttr::AT_AssertExclusiveLock:
81397330f729Sjoerg handleAssertExclusiveLockAttr(S, D, AL);
81407330f729Sjoerg break;
81417330f729Sjoerg case ParsedAttr::AT_AssertSharedLock:
81427330f729Sjoerg handleAssertSharedLockAttr(S, D, AL);
81437330f729Sjoerg break;
81447330f729Sjoerg case ParsedAttr::AT_PtGuardedVar:
81457330f729Sjoerg handlePtGuardedVarAttr(S, D, AL);
81467330f729Sjoerg break;
81477330f729Sjoerg case ParsedAttr::AT_NoSanitize:
81487330f729Sjoerg handleNoSanitizeAttr(S, D, AL);
81497330f729Sjoerg break;
81507330f729Sjoerg case ParsedAttr::AT_NoSanitizeSpecific:
81517330f729Sjoerg handleNoSanitizeSpecificAttr(S, D, AL);
81527330f729Sjoerg break;
81537330f729Sjoerg case ParsedAttr::AT_GuardedBy:
81547330f729Sjoerg handleGuardedByAttr(S, D, AL);
81557330f729Sjoerg break;
81567330f729Sjoerg case ParsedAttr::AT_PtGuardedBy:
81577330f729Sjoerg handlePtGuardedByAttr(S, D, AL);
81587330f729Sjoerg break;
81597330f729Sjoerg case ParsedAttr::AT_ExclusiveTrylockFunction:
81607330f729Sjoerg handleExclusiveTrylockFunctionAttr(S, D, AL);
81617330f729Sjoerg break;
81627330f729Sjoerg case ParsedAttr::AT_LockReturned:
81637330f729Sjoerg handleLockReturnedAttr(S, D, AL);
81647330f729Sjoerg break;
81657330f729Sjoerg case ParsedAttr::AT_LocksExcluded:
81667330f729Sjoerg handleLocksExcludedAttr(S, D, AL);
81677330f729Sjoerg break;
81687330f729Sjoerg case ParsedAttr::AT_SharedTrylockFunction:
81697330f729Sjoerg handleSharedTrylockFunctionAttr(S, D, AL);
81707330f729Sjoerg break;
81717330f729Sjoerg case ParsedAttr::AT_AcquiredBefore:
81727330f729Sjoerg handleAcquiredBeforeAttr(S, D, AL);
81737330f729Sjoerg break;
81747330f729Sjoerg case ParsedAttr::AT_AcquiredAfter:
81757330f729Sjoerg handleAcquiredAfterAttr(S, D, AL);
81767330f729Sjoerg break;
81777330f729Sjoerg
81787330f729Sjoerg // Capability analysis attributes.
81797330f729Sjoerg case ParsedAttr::AT_Capability:
81807330f729Sjoerg case ParsedAttr::AT_Lockable:
81817330f729Sjoerg handleCapabilityAttr(S, D, AL);
81827330f729Sjoerg break;
81837330f729Sjoerg case ParsedAttr::AT_RequiresCapability:
81847330f729Sjoerg handleRequiresCapabilityAttr(S, D, AL);
81857330f729Sjoerg break;
81867330f729Sjoerg
81877330f729Sjoerg case ParsedAttr::AT_AssertCapability:
81887330f729Sjoerg handleAssertCapabilityAttr(S, D, AL);
81897330f729Sjoerg break;
81907330f729Sjoerg case ParsedAttr::AT_AcquireCapability:
81917330f729Sjoerg handleAcquireCapabilityAttr(S, D, AL);
81927330f729Sjoerg break;
81937330f729Sjoerg case ParsedAttr::AT_ReleaseCapability:
81947330f729Sjoerg handleReleaseCapabilityAttr(S, D, AL);
81957330f729Sjoerg break;
81967330f729Sjoerg case ParsedAttr::AT_TryAcquireCapability:
81977330f729Sjoerg handleTryAcquireCapabilityAttr(S, D, AL);
81987330f729Sjoerg break;
81997330f729Sjoerg
82007330f729Sjoerg // Consumed analysis attributes.
82017330f729Sjoerg case ParsedAttr::AT_Consumable:
82027330f729Sjoerg handleConsumableAttr(S, D, AL);
82037330f729Sjoerg break;
82047330f729Sjoerg case ParsedAttr::AT_CallableWhen:
82057330f729Sjoerg handleCallableWhenAttr(S, D, AL);
82067330f729Sjoerg break;
82077330f729Sjoerg case ParsedAttr::AT_ParamTypestate:
82087330f729Sjoerg handleParamTypestateAttr(S, D, AL);
82097330f729Sjoerg break;
82107330f729Sjoerg case ParsedAttr::AT_ReturnTypestate:
82117330f729Sjoerg handleReturnTypestateAttr(S, D, AL);
82127330f729Sjoerg break;
82137330f729Sjoerg case ParsedAttr::AT_SetTypestate:
82147330f729Sjoerg handleSetTypestateAttr(S, D, AL);
82157330f729Sjoerg break;
82167330f729Sjoerg case ParsedAttr::AT_TestTypestate:
82177330f729Sjoerg handleTestTypestateAttr(S, D, AL);
82187330f729Sjoerg break;
82197330f729Sjoerg
82207330f729Sjoerg // Type safety attributes.
82217330f729Sjoerg case ParsedAttr::AT_ArgumentWithTypeTag:
82227330f729Sjoerg handleArgumentWithTypeTagAttr(S, D, AL);
82237330f729Sjoerg break;
82247330f729Sjoerg case ParsedAttr::AT_TypeTagForDatatype:
82257330f729Sjoerg handleTypeTagForDatatypeAttr(S, D, AL);
82267330f729Sjoerg break;
8227*e038c9c4Sjoerg
8228*e038c9c4Sjoerg // Swift attributes.
8229*e038c9c4Sjoerg case ParsedAttr::AT_SwiftAsyncName:
8230*e038c9c4Sjoerg handleSwiftAsyncName(S, D, AL);
82317330f729Sjoerg break;
8232*e038c9c4Sjoerg case ParsedAttr::AT_SwiftAttr:
8233*e038c9c4Sjoerg handleSwiftAttrAttr(S, D, AL);
82347330f729Sjoerg break;
8235*e038c9c4Sjoerg case ParsedAttr::AT_SwiftBridge:
8236*e038c9c4Sjoerg handleSwiftBridge(S, D, AL);
8237*e038c9c4Sjoerg break;
8238*e038c9c4Sjoerg case ParsedAttr::AT_SwiftError:
8239*e038c9c4Sjoerg handleSwiftError(S, D, AL);
8240*e038c9c4Sjoerg break;
8241*e038c9c4Sjoerg case ParsedAttr::AT_SwiftName:
8242*e038c9c4Sjoerg handleSwiftName(S, D, AL);
8243*e038c9c4Sjoerg break;
8244*e038c9c4Sjoerg case ParsedAttr::AT_SwiftNewType:
8245*e038c9c4Sjoerg handleSwiftNewType(S, D, AL);
8246*e038c9c4Sjoerg break;
8247*e038c9c4Sjoerg case ParsedAttr::AT_SwiftAsync:
8248*e038c9c4Sjoerg handleSwiftAsyncAttr(S, D, AL);
8249*e038c9c4Sjoerg break;
8250*e038c9c4Sjoerg case ParsedAttr::AT_SwiftAsyncError:
8251*e038c9c4Sjoerg handleSwiftAsyncError(S, D, AL);
8252*e038c9c4Sjoerg break;
8253*e038c9c4Sjoerg
82547330f729Sjoerg // XRay attributes.
82557330f729Sjoerg case ParsedAttr::AT_XRayLogArgs:
82567330f729Sjoerg handleXRayLogArgsAttr(S, D, AL);
82577330f729Sjoerg break;
82587330f729Sjoerg
8259*e038c9c4Sjoerg case ParsedAttr::AT_PatchableFunctionEntry:
8260*e038c9c4Sjoerg handlePatchableFunctionEntryAttr(S, D, AL);
82617330f729Sjoerg break;
82627330f729Sjoerg
82637330f729Sjoerg case ParsedAttr::AT_AlwaysDestroy:
82647330f729Sjoerg case ParsedAttr::AT_NoDestroy:
82657330f729Sjoerg handleDestroyAttr(S, D, AL);
82667330f729Sjoerg break;
82677330f729Sjoerg
82687330f729Sjoerg case ParsedAttr::AT_Uninitialized:
82697330f729Sjoerg handleUninitializedAttr(S, D, AL);
82707330f729Sjoerg break;
82717330f729Sjoerg
82727330f729Sjoerg case ParsedAttr::AT_ObjCExternallyRetained:
82737330f729Sjoerg handleObjCExternallyRetainedAttr(S, D, AL);
82747330f729Sjoerg break;
82757330f729Sjoerg
82767330f729Sjoerg case ParsedAttr::AT_MIGServerRoutine:
82777330f729Sjoerg handleMIGServerRoutineAttr(S, D, AL);
82787330f729Sjoerg break;
82797330f729Sjoerg
82807330f729Sjoerg case ParsedAttr::AT_MSAllocator:
82817330f729Sjoerg handleMSAllocatorAttr(S, D, AL);
82827330f729Sjoerg break;
82837330f729Sjoerg
8284*e038c9c4Sjoerg case ParsedAttr::AT_ArmBuiltinAlias:
8285*e038c9c4Sjoerg handleArmBuiltinAliasAttr(S, D, AL);
8286*e038c9c4Sjoerg break;
8287*e038c9c4Sjoerg
8288*e038c9c4Sjoerg case ParsedAttr::AT_AcquireHandle:
8289*e038c9c4Sjoerg handleAcquireHandleAttr(S, D, AL);
8290*e038c9c4Sjoerg break;
8291*e038c9c4Sjoerg
8292*e038c9c4Sjoerg case ParsedAttr::AT_ReleaseHandle:
8293*e038c9c4Sjoerg handleHandleAttr<ReleaseHandleAttr>(S, D, AL);
8294*e038c9c4Sjoerg break;
8295*e038c9c4Sjoerg
8296*e038c9c4Sjoerg case ParsedAttr::AT_UseHandle:
8297*e038c9c4Sjoerg handleHandleAttr<UseHandleAttr>(S, D, AL);
8298*e038c9c4Sjoerg break;
8299*e038c9c4Sjoerg
8300*e038c9c4Sjoerg case ParsedAttr::AT_EnforceTCB:
8301*e038c9c4Sjoerg handleEnforceTCBAttr<EnforceTCBAttr, EnforceTCBLeafAttr>(S, D, AL);
8302*e038c9c4Sjoerg break;
8303*e038c9c4Sjoerg
8304*e038c9c4Sjoerg case ParsedAttr::AT_EnforceTCBLeaf:
8305*e038c9c4Sjoerg handleEnforceTCBAttr<EnforceTCBLeafAttr, EnforceTCBAttr>(S, D, AL);
8306*e038c9c4Sjoerg break;
8307*e038c9c4Sjoerg
8308*e038c9c4Sjoerg case ParsedAttr::AT_BuiltinAlias:
8309*e038c9c4Sjoerg handleBuiltinAliasAttr(S, D, AL);
83107330f729Sjoerg break;
83117330f729Sjoerg }
83127330f729Sjoerg }
83137330f729Sjoerg
83147330f729Sjoerg /// ProcessDeclAttributeList - Apply all the decl attributes in the specified
83157330f729Sjoerg /// attribute list to the specified decl, ignoring any type attributes.
ProcessDeclAttributeList(Scope * S,Decl * D,const ParsedAttributesView & AttrList,bool IncludeCXX11Attributes)83167330f729Sjoerg void Sema::ProcessDeclAttributeList(Scope *S, Decl *D,
83177330f729Sjoerg const ParsedAttributesView &AttrList,
83187330f729Sjoerg bool IncludeCXX11Attributes) {
83197330f729Sjoerg if (AttrList.empty())
83207330f729Sjoerg return;
83217330f729Sjoerg
83227330f729Sjoerg for (const ParsedAttr &AL : AttrList)
83237330f729Sjoerg ProcessDeclAttribute(*this, S, D, AL, IncludeCXX11Attributes);
83247330f729Sjoerg
83257330f729Sjoerg // FIXME: We should be able to handle these cases in TableGen.
83267330f729Sjoerg // GCC accepts
83277330f729Sjoerg // static int a9 __attribute__((weakref));
83287330f729Sjoerg // but that looks really pointless. We reject it.
83297330f729Sjoerg if (D->hasAttr<WeakRefAttr>() && !D->hasAttr<AliasAttr>()) {
83307330f729Sjoerg Diag(AttrList.begin()->getLoc(), diag::err_attribute_weakref_without_alias)
83317330f729Sjoerg << cast<NamedDecl>(D);
83327330f729Sjoerg D->dropAttr<WeakRefAttr>();
83337330f729Sjoerg return;
83347330f729Sjoerg }
83357330f729Sjoerg
83367330f729Sjoerg // FIXME: We should be able to handle this in TableGen as well. It would be
83377330f729Sjoerg // good to have a way to specify "these attributes must appear as a group",
83387330f729Sjoerg // for these. Additionally, it would be good to have a way to specify "these
83397330f729Sjoerg // attribute must never appear as a group" for attributes like cold and hot.
83407330f729Sjoerg if (!D->hasAttr<OpenCLKernelAttr>()) {
83417330f729Sjoerg // These attributes cannot be applied to a non-kernel function.
83427330f729Sjoerg if (const auto *A = D->getAttr<ReqdWorkGroupSizeAttr>()) {
83437330f729Sjoerg // FIXME: This emits a different error message than
83447330f729Sjoerg // diag::err_attribute_wrong_decl_type + ExpectedKernelFunction.
83457330f729Sjoerg Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
83467330f729Sjoerg D->setInvalidDecl();
83477330f729Sjoerg } else if (const auto *A = D->getAttr<WorkGroupSizeHintAttr>()) {
83487330f729Sjoerg Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
83497330f729Sjoerg D->setInvalidDecl();
83507330f729Sjoerg } else if (const auto *A = D->getAttr<VecTypeHintAttr>()) {
83517330f729Sjoerg Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
83527330f729Sjoerg D->setInvalidDecl();
83537330f729Sjoerg } else if (const auto *A = D->getAttr<OpenCLIntelReqdSubGroupSizeAttr>()) {
83547330f729Sjoerg Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
83557330f729Sjoerg D->setInvalidDecl();
83567330f729Sjoerg } else if (!D->hasAttr<CUDAGlobalAttr>()) {
83577330f729Sjoerg if (const auto *A = D->getAttr<AMDGPUFlatWorkGroupSizeAttr>()) {
83587330f729Sjoerg Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
83597330f729Sjoerg << A << ExpectedKernelFunction;
83607330f729Sjoerg D->setInvalidDecl();
83617330f729Sjoerg } else if (const auto *A = D->getAttr<AMDGPUWavesPerEUAttr>()) {
83627330f729Sjoerg Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
83637330f729Sjoerg << A << ExpectedKernelFunction;
83647330f729Sjoerg D->setInvalidDecl();
83657330f729Sjoerg } else if (const auto *A = D->getAttr<AMDGPUNumSGPRAttr>()) {
83667330f729Sjoerg Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
83677330f729Sjoerg << A << ExpectedKernelFunction;
83687330f729Sjoerg D->setInvalidDecl();
83697330f729Sjoerg } else if (const auto *A = D->getAttr<AMDGPUNumVGPRAttr>()) {
83707330f729Sjoerg Diag(D->getLocation(), diag::err_attribute_wrong_decl_type)
83717330f729Sjoerg << A << ExpectedKernelFunction;
83727330f729Sjoerg D->setInvalidDecl();
83737330f729Sjoerg }
83747330f729Sjoerg }
83757330f729Sjoerg }
83767330f729Sjoerg
83777330f729Sjoerg // Do this check after processing D's attributes because the attribute
83787330f729Sjoerg // objc_method_family can change whether the given method is in the init
83797330f729Sjoerg // family, and it can be applied after objc_designated_initializer. This is a
83807330f729Sjoerg // bit of a hack, but we need it to be compatible with versions of clang that
83817330f729Sjoerg // processed the attribute list in the wrong order.
83827330f729Sjoerg if (D->hasAttr<ObjCDesignatedInitializerAttr>() &&
83837330f729Sjoerg cast<ObjCMethodDecl>(D)->getMethodFamily() != OMF_init) {
83847330f729Sjoerg Diag(D->getLocation(), diag::err_designated_init_attr_non_init);
83857330f729Sjoerg D->dropAttr<ObjCDesignatedInitializerAttr>();
83867330f729Sjoerg }
83877330f729Sjoerg }
83887330f729Sjoerg
8389*e038c9c4Sjoerg // Helper for delayed processing TransparentUnion or BPFPreserveAccessIndexAttr
8390*e038c9c4Sjoerg // attribute.
ProcessDeclAttributeDelayed(Decl * D,const ParsedAttributesView & AttrList)83917330f729Sjoerg void Sema::ProcessDeclAttributeDelayed(Decl *D,
83927330f729Sjoerg const ParsedAttributesView &AttrList) {
83937330f729Sjoerg for (const ParsedAttr &AL : AttrList)
83947330f729Sjoerg if (AL.getKind() == ParsedAttr::AT_TransparentUnion) {
83957330f729Sjoerg handleTransparentUnionAttr(*this, D, AL);
83967330f729Sjoerg break;
83977330f729Sjoerg }
8398*e038c9c4Sjoerg
8399*e038c9c4Sjoerg // For BPFPreserveAccessIndexAttr, we want to populate the attributes
8400*e038c9c4Sjoerg // to fields and inner records as well.
8401*e038c9c4Sjoerg if (D && D->hasAttr<BPFPreserveAccessIndexAttr>())
8402*e038c9c4Sjoerg handleBPFPreserveAIRecord(*this, cast<RecordDecl>(D));
84037330f729Sjoerg }
84047330f729Sjoerg
84057330f729Sjoerg // Annotation attributes are the only attributes allowed after an access
84067330f729Sjoerg // specifier.
ProcessAccessDeclAttributeList(AccessSpecDecl * ASDecl,const ParsedAttributesView & AttrList)84077330f729Sjoerg bool Sema::ProcessAccessDeclAttributeList(
84087330f729Sjoerg AccessSpecDecl *ASDecl, const ParsedAttributesView &AttrList) {
84097330f729Sjoerg for (const ParsedAttr &AL : AttrList) {
84107330f729Sjoerg if (AL.getKind() == ParsedAttr::AT_Annotate) {
84117330f729Sjoerg ProcessDeclAttribute(*this, nullptr, ASDecl, AL, AL.isCXX11Attribute());
84127330f729Sjoerg } else {
84137330f729Sjoerg Diag(AL.getLoc(), diag::err_only_annotate_after_access_spec);
84147330f729Sjoerg return true;
84157330f729Sjoerg }
84167330f729Sjoerg }
84177330f729Sjoerg return false;
84187330f729Sjoerg }
84197330f729Sjoerg
84207330f729Sjoerg /// checkUnusedDeclAttributes - Check a list of attributes to see if it
84217330f729Sjoerg /// contains any decl attributes that we should warn about.
checkUnusedDeclAttributes(Sema & S,const ParsedAttributesView & A)84227330f729Sjoerg static void checkUnusedDeclAttributes(Sema &S, const ParsedAttributesView &A) {
84237330f729Sjoerg for (const ParsedAttr &AL : A) {
84247330f729Sjoerg // Only warn if the attribute is an unignored, non-type attribute.
84257330f729Sjoerg if (AL.isUsedAsTypeAttr() || AL.isInvalid())
84267330f729Sjoerg continue;
84277330f729Sjoerg if (AL.getKind() == ParsedAttr::IgnoredAttribute)
84287330f729Sjoerg continue;
84297330f729Sjoerg
84307330f729Sjoerg if (AL.getKind() == ParsedAttr::UnknownAttribute) {
84317330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored)
84327330f729Sjoerg << AL << AL.getRange();
84337330f729Sjoerg } else {
84347330f729Sjoerg S.Diag(AL.getLoc(), diag::warn_attribute_not_on_decl) << AL
84357330f729Sjoerg << AL.getRange();
84367330f729Sjoerg }
84377330f729Sjoerg }
84387330f729Sjoerg }
84397330f729Sjoerg
84407330f729Sjoerg /// checkUnusedDeclAttributes - Given a declarator which is not being
84417330f729Sjoerg /// used to build a declaration, complain about any decl attributes
84427330f729Sjoerg /// which might be lying around on it.
checkUnusedDeclAttributes(Declarator & D)84437330f729Sjoerg void Sema::checkUnusedDeclAttributes(Declarator &D) {
84447330f729Sjoerg ::checkUnusedDeclAttributes(*this, D.getDeclSpec().getAttributes());
84457330f729Sjoerg ::checkUnusedDeclAttributes(*this, D.getAttributes());
84467330f729Sjoerg for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i)
84477330f729Sjoerg ::checkUnusedDeclAttributes(*this, D.getTypeObject(i).getAttrs());
84487330f729Sjoerg }
84497330f729Sjoerg
84507330f729Sjoerg /// DeclClonePragmaWeak - clone existing decl (maybe definition),
84517330f729Sjoerg /// \#pragma weak needs a non-definition decl and source may not have one.
DeclClonePragmaWeak(NamedDecl * ND,IdentifierInfo * II,SourceLocation Loc)84527330f729Sjoerg NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II,
84537330f729Sjoerg SourceLocation Loc) {
84547330f729Sjoerg assert(isa<FunctionDecl>(ND) || isa<VarDecl>(ND));
84557330f729Sjoerg NamedDecl *NewD = nullptr;
84567330f729Sjoerg if (auto *FD = dyn_cast<FunctionDecl>(ND)) {
84577330f729Sjoerg FunctionDecl *NewFD;
84587330f729Sjoerg // FIXME: Missing call to CheckFunctionDeclaration().
84597330f729Sjoerg // FIXME: Mangling?
84607330f729Sjoerg // FIXME: Is the qualifier info correct?
84617330f729Sjoerg // FIXME: Is the DeclContext correct?
84627330f729Sjoerg NewFD = FunctionDecl::Create(
84637330f729Sjoerg FD->getASTContext(), FD->getDeclContext(), Loc, Loc,
84647330f729Sjoerg DeclarationName(II), FD->getType(), FD->getTypeSourceInfo(), SC_None,
8465*e038c9c4Sjoerg false /*isInlineSpecified*/, FD->hasPrototype(),
8466*e038c9c4Sjoerg ConstexprSpecKind::Unspecified, FD->getTrailingRequiresClause());
84677330f729Sjoerg NewD = NewFD;
84687330f729Sjoerg
84697330f729Sjoerg if (FD->getQualifier())
84707330f729Sjoerg NewFD->setQualifierInfo(FD->getQualifierLoc());
84717330f729Sjoerg
84727330f729Sjoerg // Fake up parameter variables; they are declared as if this were
84737330f729Sjoerg // a typedef.
84747330f729Sjoerg QualType FDTy = FD->getType();
84757330f729Sjoerg if (const auto *FT = FDTy->getAs<FunctionProtoType>()) {
84767330f729Sjoerg SmallVector<ParmVarDecl*, 16> Params;
84777330f729Sjoerg for (const auto &AI : FT->param_types()) {
84787330f729Sjoerg ParmVarDecl *Param = BuildParmVarDeclForTypedef(NewFD, Loc, AI);
84797330f729Sjoerg Param->setScopeInfo(0, Params.size());
84807330f729Sjoerg Params.push_back(Param);
84817330f729Sjoerg }
84827330f729Sjoerg NewFD->setParams(Params);
84837330f729Sjoerg }
84847330f729Sjoerg } else if (auto *VD = dyn_cast<VarDecl>(ND)) {
84857330f729Sjoerg NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(),
84867330f729Sjoerg VD->getInnerLocStart(), VD->getLocation(), II,
84877330f729Sjoerg VD->getType(), VD->getTypeSourceInfo(),
84887330f729Sjoerg VD->getStorageClass());
84897330f729Sjoerg if (VD->getQualifier())
84907330f729Sjoerg cast<VarDecl>(NewD)->setQualifierInfo(VD->getQualifierLoc());
84917330f729Sjoerg }
84927330f729Sjoerg return NewD;
84937330f729Sjoerg }
84947330f729Sjoerg
84957330f729Sjoerg /// DeclApplyPragmaWeak - A declaration (maybe definition) needs \#pragma weak
84967330f729Sjoerg /// applied to it, possibly with an alias.
DeclApplyPragmaWeak(Scope * S,NamedDecl * ND,WeakInfo & W)84977330f729Sjoerg void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) {
84987330f729Sjoerg if (W.getUsed()) return; // only do this once
84997330f729Sjoerg W.setUsed(true);
85007330f729Sjoerg if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...))
85017330f729Sjoerg IdentifierInfo *NDId = ND->getIdentifier();
85027330f729Sjoerg NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias(), W.getLocation());
85037330f729Sjoerg NewD->addAttr(
85047330f729Sjoerg AliasAttr::CreateImplicit(Context, NDId->getName(), W.getLocation()));
85057330f729Sjoerg NewD->addAttr(WeakAttr::CreateImplicit(Context, W.getLocation(),
85067330f729Sjoerg AttributeCommonInfo::AS_Pragma));
85077330f729Sjoerg WeakTopLevelDecl.push_back(NewD);
85087330f729Sjoerg // FIXME: "hideous" code from Sema::LazilyCreateBuiltin
85097330f729Sjoerg // to insert Decl at TU scope, sorry.
85107330f729Sjoerg DeclContext *SavedContext = CurContext;
85117330f729Sjoerg CurContext = Context.getTranslationUnitDecl();
85127330f729Sjoerg NewD->setDeclContext(CurContext);
85137330f729Sjoerg NewD->setLexicalDeclContext(CurContext);
85147330f729Sjoerg PushOnScopeChains(NewD, S);
85157330f729Sjoerg CurContext = SavedContext;
85167330f729Sjoerg } else { // just add weak to existing
85177330f729Sjoerg ND->addAttr(WeakAttr::CreateImplicit(Context, W.getLocation(),
85187330f729Sjoerg AttributeCommonInfo::AS_Pragma));
85197330f729Sjoerg }
85207330f729Sjoerg }
85217330f729Sjoerg
ProcessPragmaWeak(Scope * S,Decl * D)85227330f729Sjoerg void Sema::ProcessPragmaWeak(Scope *S, Decl *D) {
85237330f729Sjoerg // It's valid to "forward-declare" #pragma weak, in which case we
85247330f729Sjoerg // have to do this.
85257330f729Sjoerg LoadExternalWeakUndeclaredIdentifiers();
85267330f729Sjoerg if (!WeakUndeclaredIdentifiers.empty()) {
85277330f729Sjoerg NamedDecl *ND = nullptr;
85287330f729Sjoerg if (auto *VD = dyn_cast<VarDecl>(D))
85297330f729Sjoerg if (VD->isExternC())
85307330f729Sjoerg ND = VD;
85317330f729Sjoerg if (auto *FD = dyn_cast<FunctionDecl>(D))
85327330f729Sjoerg if (FD->isExternC())
85337330f729Sjoerg ND = FD;
85347330f729Sjoerg if (ND) {
85357330f729Sjoerg if (IdentifierInfo *Id = ND->getIdentifier()) {
85367330f729Sjoerg auto I = WeakUndeclaredIdentifiers.find(Id);
85377330f729Sjoerg if (I != WeakUndeclaredIdentifiers.end()) {
85387330f729Sjoerg WeakInfo W = I->second;
85397330f729Sjoerg DeclApplyPragmaWeak(S, ND, W);
85407330f729Sjoerg WeakUndeclaredIdentifiers[Id] = W;
85417330f729Sjoerg }
85427330f729Sjoerg }
85437330f729Sjoerg }
85447330f729Sjoerg }
85457330f729Sjoerg }
85467330f729Sjoerg
85477330f729Sjoerg /// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in
85487330f729Sjoerg /// it, apply them to D. This is a bit tricky because PD can have attributes
85497330f729Sjoerg /// specified in many different places, and we need to find and apply them all.
ProcessDeclAttributes(Scope * S,Decl * D,const Declarator & PD)85507330f729Sjoerg void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) {
85517330f729Sjoerg // Apply decl attributes from the DeclSpec if present.
85527330f729Sjoerg if (!PD.getDeclSpec().getAttributes().empty())
85537330f729Sjoerg ProcessDeclAttributeList(S, D, PD.getDeclSpec().getAttributes());
85547330f729Sjoerg
85557330f729Sjoerg // Walk the declarator structure, applying decl attributes that were in a type
85567330f729Sjoerg // position to the decl itself. This handles cases like:
85577330f729Sjoerg // int *__attr__(x)** D;
85587330f729Sjoerg // when X is a decl attribute.
85597330f729Sjoerg for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i)
85607330f729Sjoerg ProcessDeclAttributeList(S, D, PD.getTypeObject(i).getAttrs(),
85617330f729Sjoerg /*IncludeCXX11Attributes=*/false);
85627330f729Sjoerg
85637330f729Sjoerg // Finally, apply any attributes on the decl itself.
85647330f729Sjoerg ProcessDeclAttributeList(S, D, PD.getAttributes());
85657330f729Sjoerg
85667330f729Sjoerg // Apply additional attributes specified by '#pragma clang attribute'.
85677330f729Sjoerg AddPragmaAttributes(S, D);
85687330f729Sjoerg }
85697330f729Sjoerg
85707330f729Sjoerg /// Is the given declaration allowed to use a forbidden type?
85717330f729Sjoerg /// If so, it'll still be annotated with an attribute that makes it
85727330f729Sjoerg /// illegal to actually use.
isForbiddenTypeAllowed(Sema & S,Decl * D,const DelayedDiagnostic & diag,UnavailableAttr::ImplicitReason & reason)85737330f729Sjoerg static bool isForbiddenTypeAllowed(Sema &S, Decl *D,
85747330f729Sjoerg const DelayedDiagnostic &diag,
85757330f729Sjoerg UnavailableAttr::ImplicitReason &reason) {
85767330f729Sjoerg // Private ivars are always okay. Unfortunately, people don't
85777330f729Sjoerg // always properly make their ivars private, even in system headers.
85787330f729Sjoerg // Plus we need to make fields okay, too.
85797330f729Sjoerg if (!isa<FieldDecl>(D) && !isa<ObjCPropertyDecl>(D) &&
85807330f729Sjoerg !isa<FunctionDecl>(D))
85817330f729Sjoerg return false;
85827330f729Sjoerg
85837330f729Sjoerg // Silently accept unsupported uses of __weak in both user and system
85847330f729Sjoerg // declarations when it's been disabled, for ease of integration with
85857330f729Sjoerg // -fno-objc-arc files. We do have to take some care against attempts
85867330f729Sjoerg // to define such things; for now, we've only done that for ivars
85877330f729Sjoerg // and properties.
85887330f729Sjoerg if ((isa<ObjCIvarDecl>(D) || isa<ObjCPropertyDecl>(D))) {
85897330f729Sjoerg if (diag.getForbiddenTypeDiagnostic() == diag::err_arc_weak_disabled ||
85907330f729Sjoerg diag.getForbiddenTypeDiagnostic() == diag::err_arc_weak_no_runtime) {
85917330f729Sjoerg reason = UnavailableAttr::IR_ForbiddenWeak;
85927330f729Sjoerg return true;
85937330f729Sjoerg }
85947330f729Sjoerg }
85957330f729Sjoerg
85967330f729Sjoerg // Allow all sorts of things in system headers.
85977330f729Sjoerg if (S.Context.getSourceManager().isInSystemHeader(D->getLocation())) {
85987330f729Sjoerg // Currently, all the failures dealt with this way are due to ARC
85997330f729Sjoerg // restrictions.
86007330f729Sjoerg reason = UnavailableAttr::IR_ARCForbiddenType;
86017330f729Sjoerg return true;
86027330f729Sjoerg }
86037330f729Sjoerg
86047330f729Sjoerg return false;
86057330f729Sjoerg }
86067330f729Sjoerg
86077330f729Sjoerg /// Handle a delayed forbidden-type diagnostic.
handleDelayedForbiddenType(Sema & S,DelayedDiagnostic & DD,Decl * D)86087330f729Sjoerg static void handleDelayedForbiddenType(Sema &S, DelayedDiagnostic &DD,
86097330f729Sjoerg Decl *D) {
86107330f729Sjoerg auto Reason = UnavailableAttr::IR_None;
86117330f729Sjoerg if (D && isForbiddenTypeAllowed(S, D, DD, Reason)) {
86127330f729Sjoerg assert(Reason && "didn't set reason?");
86137330f729Sjoerg D->addAttr(UnavailableAttr::CreateImplicit(S.Context, "", Reason, DD.Loc));
86147330f729Sjoerg return;
86157330f729Sjoerg }
86167330f729Sjoerg if (S.getLangOpts().ObjCAutoRefCount)
86177330f729Sjoerg if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
86187330f729Sjoerg // FIXME: we may want to suppress diagnostics for all
86197330f729Sjoerg // kind of forbidden type messages on unavailable functions.
86207330f729Sjoerg if (FD->hasAttr<UnavailableAttr>() &&
86217330f729Sjoerg DD.getForbiddenTypeDiagnostic() ==
86227330f729Sjoerg diag::err_arc_array_param_no_ownership) {
86237330f729Sjoerg DD.Triggered = true;
86247330f729Sjoerg return;
86257330f729Sjoerg }
86267330f729Sjoerg }
86277330f729Sjoerg
86287330f729Sjoerg S.Diag(DD.Loc, DD.getForbiddenTypeDiagnostic())
86297330f729Sjoerg << DD.getForbiddenTypeOperand() << DD.getForbiddenTypeArgument();
86307330f729Sjoerg DD.Triggered = true;
86317330f729Sjoerg }
86327330f729Sjoerg
86337330f729Sjoerg
PopParsingDeclaration(ParsingDeclState state,Decl * decl)86347330f729Sjoerg void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) {
86357330f729Sjoerg assert(DelayedDiagnostics.getCurrentPool());
86367330f729Sjoerg DelayedDiagnosticPool &poppedPool = *DelayedDiagnostics.getCurrentPool();
86377330f729Sjoerg DelayedDiagnostics.popWithoutEmitting(state);
86387330f729Sjoerg
86397330f729Sjoerg // When delaying diagnostics to run in the context of a parsed
86407330f729Sjoerg // declaration, we only want to actually emit anything if parsing
86417330f729Sjoerg // succeeds.
86427330f729Sjoerg if (!decl) return;
86437330f729Sjoerg
86447330f729Sjoerg // We emit all the active diagnostics in this pool or any of its
86457330f729Sjoerg // parents. In general, we'll get one pool for the decl spec
86467330f729Sjoerg // and a child pool for each declarator; in a decl group like:
86477330f729Sjoerg // deprecated_typedef foo, *bar, baz();
86487330f729Sjoerg // only the declarator pops will be passed decls. This is correct;
86497330f729Sjoerg // we really do need to consider delayed diagnostics from the decl spec
86507330f729Sjoerg // for each of the different declarations.
86517330f729Sjoerg const DelayedDiagnosticPool *pool = &poppedPool;
86527330f729Sjoerg do {
86537330f729Sjoerg bool AnyAccessFailures = false;
86547330f729Sjoerg for (DelayedDiagnosticPool::pool_iterator
86557330f729Sjoerg i = pool->pool_begin(), e = pool->pool_end(); i != e; ++i) {
86567330f729Sjoerg // This const_cast is a bit lame. Really, Triggered should be mutable.
86577330f729Sjoerg DelayedDiagnostic &diag = const_cast<DelayedDiagnostic&>(*i);
86587330f729Sjoerg if (diag.Triggered)
86597330f729Sjoerg continue;
86607330f729Sjoerg
86617330f729Sjoerg switch (diag.Kind) {
86627330f729Sjoerg case DelayedDiagnostic::Availability:
86637330f729Sjoerg // Don't bother giving deprecation/unavailable diagnostics if
86647330f729Sjoerg // the decl is invalid.
86657330f729Sjoerg if (!decl->isInvalidDecl())
8666*e038c9c4Sjoerg handleDelayedAvailabilityCheck(diag, decl);
86677330f729Sjoerg break;
86687330f729Sjoerg
86697330f729Sjoerg case DelayedDiagnostic::Access:
86707330f729Sjoerg // Only produce one access control diagnostic for a structured binding
86717330f729Sjoerg // declaration: we don't need to tell the user that all the fields are
86727330f729Sjoerg // inaccessible one at a time.
86737330f729Sjoerg if (AnyAccessFailures && isa<DecompositionDecl>(decl))
86747330f729Sjoerg continue;
86757330f729Sjoerg HandleDelayedAccessCheck(diag, decl);
86767330f729Sjoerg if (diag.Triggered)
86777330f729Sjoerg AnyAccessFailures = true;
86787330f729Sjoerg break;
86797330f729Sjoerg
86807330f729Sjoerg case DelayedDiagnostic::ForbiddenType:
86817330f729Sjoerg handleDelayedForbiddenType(*this, diag, decl);
86827330f729Sjoerg break;
86837330f729Sjoerg }
86847330f729Sjoerg }
86857330f729Sjoerg } while ((pool = pool->getParent()));
86867330f729Sjoerg }
86877330f729Sjoerg
86887330f729Sjoerg /// Given a set of delayed diagnostics, re-emit them as if they had
86897330f729Sjoerg /// been delayed in the current context instead of in the given pool.
86907330f729Sjoerg /// Essentially, this just moves them to the current pool.
redelayDiagnostics(DelayedDiagnosticPool & pool)86917330f729Sjoerg void Sema::redelayDiagnostics(DelayedDiagnosticPool &pool) {
86927330f729Sjoerg DelayedDiagnosticPool *curPool = DelayedDiagnostics.getCurrentPool();
86937330f729Sjoerg assert(curPool && "re-emitting in undelayed context not supported");
86947330f729Sjoerg curPool->steal(pool);
86957330f729Sjoerg }
8696